diff --git a/Layout/andom-tec/Emailtemplates/attachments/new_order_spin.pdf.php b/Layout/andom-tec/Emailtemplates/attachments/new_order_spin.pdf.php new file mode 100644 index 000000000..389270f18 --- /dev/null +++ b/Layout/andom-tec/Emailtemplates/attachments/new_order_spin.pdf.php @@ -0,0 +1,83 @@ +setReturnValue([ + 'filename' => "Wichtige Kundeninformation ".$owner->customer_number.".pdf" + ]); +?> + + + + + Wichtige Kundeninformation zu Ihrem Glasfaseranschluss + + + + + + + + + + + + + + +
+ +  
+ + +
+ +
+ company): ?> + company)?>
+ + getFullName()): ?> + getFullName()?>
+ + street?>
+ zip?> city?> +
+ +
+ +
+

Wichtige Kundeninformation zu Ihrem
Glasfaseranschluss

+
+ +
+ +
+

Sehr geehrte Damen und Herren,

+

wir freuen uns sehr, dass Sie sich für einen Glasfaseranschluss im Netz der company?> entschieden haben. Hiermit möchten wir Ihnen gerne den Eingang Ihrer Bestellung bestätigen.

+

Bezüglich der gegebenenfalls erforderlichen Termine für die Installation melden wir uns (bzw. unsere Partner vom Leitungsbau) sobald die Herstellung möglich ist.

+

Ihr persönlicher Service-PIN lautet: spin?>

+

Gemäß der EU-Datenschutzverordnung sind wir dazu verpflichtet, mit den uns anvertrauten Kundendaten sorgsam umzugehen. Dazu gehört die Abfrage eines Service-PINs mit welchem Sie bei uns auch + telefonische Auskünfte (z.B. vergessene Passwörter, Rechnungsauskünfte, etc.) erhalten können. Unsere Mitarbeiter werden Sie vor Beantwortung Ihrer Fragen um die Nennung des Service-PINs bitte. + Bitte haben Sie Verständnis, dass wir ohne korrekte Nennung Ihres PINs keine Auskünfte erteilen können.

+
+ +
 
+ +
+

Sollten Sie noch Fragen haben, erreichen Sie uns per Mail an email?> oder telefonisch unter der Rufnummer phone?>.

+
+ +
 
+ +
+

Mit freundlichen Grüßen,

+
+ +
 
+ +
+

Ihr Team der company?>

+
+ + + \ No newline at end of file diff --git a/Layout/andom-tec/Emailtemplates/customer/new_order.php b/Layout/andom-tec/Emailtemplates/customer/new_order.php new file mode 100644 index 000000000..0c2868e77 --- /dev/null +++ b/Layout/andom-tec/Emailtemplates/customer/new_order.php @@ -0,0 +1,15 @@ +setReturnValue([ + 'subject' => "Ihre Bestellung wurde erfasst", + 'from_email' => $netowner->email, + 'from_email_name' => $netowner->company." Kundenservice" + ]); +?> + +Sehr geehrte Damen und Herren, + +im Anhang finden Sie weitere Informationen zur Ihrer Glasfaserbestellung, sowie Ihren persönlichen Service-PIN. + +Mit freundlichen Grüßen, + +Ihr Team der company?> diff --git a/Layout/andom-tec/Emailtemplates/order/billing_external_energie.php b/Layout/andom-tec/Emailtemplates/order/billing_external_energie.php new file mode 100644 index 000000000..a5a441533 --- /dev/null +++ b/Layout/andom-tec/Emailtemplates/order/billing_external_energie.php @@ -0,0 +1,131 @@ +terminations[0]->id; + $op = OrderProductModel::getFirst(['order_id' => $order->id, 'termination_id' => $term_id]); + + $billing_start = date('U'); + if($op->billing_delay) { + $billing_start = strtotime("+".$op->billing_delay." months"); + } + + $subject = ""; + if($order->upgrade) { + $subject .= "[UPGRADE] "; + } + $subject .= $order->partner_number." - " + ."hergestellt am ".date("d.m.Y", $order->finish_date) . " - " + ."Verrechnung ab ".date("m", $billing_start)."/".date("Y", $billing_start)." - " + .str_replace("\n", " ", str_replace("\r", "", $order->owner->getCompanyOrName())); + + $this->setReturnValue([ + 'subject' => $subject, + + 'from_email' => TT_OUTGOING_EMAIL, + 'from_email_name' => "XINON Partnerservice" + ]); + +?> +upgrade): ?> +Achtung: UPGRADE + + + +Rechnungspositionen +==================== + +Anzahl | Produktname | Verrechungsperiode | Preis periodisch | Preis Herstellung +----------------------------------------------------------------------------------------------------------------------- +products as $op): ?> +amount,0,12))?> | product->name,0,42))))?> | billing_period == 12) ? "Jährlich " : (($op->billing_period == 1) ? "Monatlich" : $op->billing_period."-monatlich")) ))?> | price,0,12))?> | EUR price_setup?> + +----------------------------------------------------------------------------------------------------------------------- + + +terminations) && count($order->terminations)): ?> +Anschluss +========== +terminations as $term): ?> +getAddress()?> + + + + + +Bestelldetails +=============== +Bestelldatum: order_date)?> + +Bestellung abgeschlossen: finish_date)?> + +Einwilligung Datenschutz: allow_contact)? "Ja" : "Nein"?> + + + +Vertragsinhaber +================ +Firma: owner->company?> + +Vorname: owner->firstname?> + +Nachname: owner->lastname?> + +Straße: owner->street?> + +PLZ: owner->zip?> + +Ort: owner->city?> + +Land: owner->country?> + +Telefon: owner->phone?> + +Fax: owner->fax?> + +Mobiltelefon: owner->mobile?> + +Email: owner->email?> + +billingaddress_id > 0 && $order->billingaddress_id != $order->owner_id): ?> + + +Rechnungsempfänger +=================== +Firma: billingaddress->company?> + +Vorname: billingaddress->firstname?> + +Nachname: billingaddress->lastname?> + +Straße: billingaddress->street?> + +PLZ: billingaddress->zip?> + +Ort: billingaddress->city?> + +Land: billingaddress->country?> + +Telefon: billingaddress->phone?> + +Fax: billingaddress->fax?> + +Mobiltelefon: billingaddress->mobile?> + +Email: billingaddress->email?> + + + + +Verrechnung +============ +billing_type == "invoice"): ?> +Verrechnungsart: Rechnung + +Verrechnungsart: SEPA Bankeinzug +Bank: bank_account_bank?> + +Kontoinhaber: bank_account_owner?> + +IBAN: bank_account_iban?> + +BIC: bank_account_bic?> + + diff --git a/Layout/andom-tec/Emailtemplates/order/fileupload/handover_report.php b/Layout/andom-tec/Emailtemplates/order/fileupload/handover_report.php new file mode 100644 index 000000000..965abe129 --- /dev/null +++ b/Layout/andom-tec/Emailtemplates/order/fileupload/handover_report.php @@ -0,0 +1,31 @@ +owner->getChildrenByType("techcontact"); +if(!is_array($contacts) || !count($contacts)) { + $contacts = [$order->owner]; +} + +$tos = []; +foreach($contacts as $contact) { + if($contact->email) { + $tos[] = $contact->email; + } +} + +$customer_string = str_replace(["\r","\n"], " ", $order->owner->getCompanyOrName()); + +$subject = "Ihr Übergabeprotokoll / Technikerstammblatt"; + +$this->setReturnValue([ + 'subject' => $subject, + 'to' => $tos, + 'from_email' => "support@xinon.at", + 'from_email_name' => "XINON Kundenservice" +]); + +?> +Sehr geehrte Damen und Herren, + +im Anhang erhalten Sie das technische Übergabeprotokoll zum Anschluss des Kunden zur weiteren Verwendung. + +Ihr XINON Team diff --git a/Layout/andom-tec/Emailtemplates/order/fileupload/order_pbx.php b/Layout/andom-tec/Emailtemplates/order/fileupload/order_pbx.php new file mode 100644 index 000000000..063957ac1 --- /dev/null +++ b/Layout/andom-tec/Emailtemplates/order/fileupload/order_pbx.php @@ -0,0 +1,19 @@ +owner->getCompanyOrName())." [".$order->owner->customer_number."]"; + +$subject = "Neue PBX-Bestellung eingelangt ($customer_string)"; + +$this->setReturnValue([ + 'subject' => $subject, + 'to' => "einkauf@xinon.at", + 'from_email' => TT_OUTGOING_EMAIL, + 'from_email_name' => TT_OUTGOING_EMAIL_NAME +]); + +?> +creator->name)?> hat die Bestellung einer Telefonanlage für den Kunden angelegt - siehe Dokument im Anhang. Bitte um technische Prüfung und Materialabklärung bzw. Herstellungsfreigabe. + +TheTool OrderROBOT (-; + +https:// $order->id])?> diff --git a/Layout/andom-tec/Emailtemplates/order/fileupload/order_project.php b/Layout/andom-tec/Emailtemplates/order/fileupload/order_project.php new file mode 100644 index 000000000..8ab9b7730 --- /dev/null +++ b/Layout/andom-tec/Emailtemplates/order/fileupload/order_project.php @@ -0,0 +1,19 @@ +owner->getCompanyOrName())." [".$order->owner->customer_number."]"; + +$subject = "Neue Projektbestellung eingelangt ($customer_string)"; + +$this->setReturnValue([ + 'subject' => $subject, + 'to' => "einkauf@xinon.at", + 'from_email' => TT_OUTGOING_EMAIL, + 'from_email_name' => TT_OUTGOING_EMAIL_NAME +]); + +?> +creator->name)?> hat eine Projektbestellung für den Kunden angelegt - siehe Dokument im Anhang. Bitte um technische Prüfung und Materialabklärung bzw. Herstellungsfreigabe. + +TheTool OrderROBOT (-; + +https:// $order->id])?> diff --git a/Layout/andom-tec/Emailtemplates/order/fileupload/sepa_form.php b/Layout/andom-tec/Emailtemplates/order/fileupload/sepa_form.php new file mode 100644 index 000000000..f624c2a07 --- /dev/null +++ b/Layout/andom-tec/Emailtemplates/order/fileupload/sepa_form.php @@ -0,0 +1,19 @@ +owner->getCompanyOrName())." [".$order->owner->customer_number."]"; + +$subject = "Neue Einzugsermächtigung eingelangt ($customer_string)"; + +$this->setReturnValue([ + 'subject' => $subject, + 'to' => "billing@xinon.at", + 'from_email' => TT_OUTGOING_EMAIL, + 'from_email_name' => TT_OUTGOING_EMAIL_NAME +]); + +?> +creator->name)?> hat soeben eine Einzugsermächtigung für den Kunden angelegt - siehe Dokument im Anhang. Bitte um Prüfung und Aktualisierung der Bankdaten des Kunden. + +TheTool OrderROBOT (-; + +https:// $order->id])?> diff --git a/Layout/andom-tec/Emailtemplates/order/fileupload/voicenumber_porting.php b/Layout/andom-tec/Emailtemplates/order/fileupload/voicenumber_porting.php new file mode 100644 index 000000000..743845049 --- /dev/null +++ b/Layout/andom-tec/Emailtemplates/order/fileupload/voicenumber_porting.php @@ -0,0 +1,19 @@ +owner->getCompanyOrName())." [".$order->owner->customer_number."]"; + +$subject = "Neue Rufnummerportierung ($customer_string)"; + +$this->setReturnValue([ + 'subject' => $subject, + 'to' => "portierung@xinon.at", + 'from_email' => TT_OUTGOING_EMAIL, + 'from_email_name' => TT_OUTGOING_EMAIL_NAME +]); + +?> +creator->name)?> hat soeben eine Rufnummerportierung für den Kunden angelegt - siehe Dokument im Anhang. Bitte um Prüfung des Herstellungstermins und Einreichung. + +TheTool OrderROBOT (-; + +https:// $order->id])?> diff --git a/Layout/andom-tec/Emailtemplates/order/int_billing_info.php b/Layout/andom-tec/Emailtemplates/order/int_billing_info.php new file mode 100644 index 000000000..54dffa218 --- /dev/null +++ b/Layout/andom-tec/Emailtemplates/order/int_billing_info.php @@ -0,0 +1,79 @@ +terminations[0]->id; + $op = OrderProductModel::getFirst(['order_id' => $order->id, 'termination_id' => $term_id]); + + if($order->finish_date) { + $billing_start = $order->finish_date; + } else { + $billing_start = date('U'); + } + + if($op->billing_delay) { + $billing_start = strtotime("+".$op->billing_delay." months"); + } + + $subject = ""; + if($order->upgrade) { + $subject .= "[UPGRADE] "; + } + $subject .= $order->terminations[0]->building->network->name." - " + ."Verr. ab ".date("m", $billing_start)."/".date("Y", $billing_start)." - " + .$order->owner->customer_number." - " + .str_replace("\n", "", str_replace("\r\n", " ", $order->owner->getCompanyOrName())); + + $this->setReturnValue([ + 'subject' => $subject, + + 'from_email' => TT_OUTGOING_EMAIL, + 'from_email_name' => TT_OUTGOING_EMAIL_NAME + ]); + + $nne_products = []; +?> +upgrade): ?> +Achtung: UPGRADE + + +Netzgebiet: terminations[0]->building->network->name?> + +Bauabschnitt: terminations[0]->building->networksection_id) ? $order->terminations[0]->building->networksection->name : "")?> + +Kundennummer: owner->customer_number?> + +Kunde: owner->getCompanyOrName()))?> + +Verrechungsstart: / + + +Rechnungspositionen +==================== + +Anzahl | Produktname | Verrechungsperiode | Preis periodisch | Preis Herstellung +----------------------------------------------------------------------------------------------------------------------- +products as $op): ?> +price_nne > 0.0) $nne_products[] = $op; ?> +amount,0,12))?> | product->name,0,42))))?> | billing_period == 12) ? "Jährlich " : (($op->billing_period == 1) ? "Monatlich" : $op->billing_period."-monatlich")) ))?> | price,0,12))?> | EUR price_setup?> + +----------------------------------------------------------------------------------------------------------------------- + + + + +Gutschriften +============= + +terminations[0]->building->network->owner): ?> +Netzeigentümer: terminations[0]->building->network->owner->getCompanyOrName()?> + + +Anzahl | Produktname | Verrechungsperiode | Bauabschnitt | NNE +----------------------------------------------------------------------------------------------------------------------- + +amount,0,12))?> | product->name,0,42))))?> | billing_period == 12) ? "Jährlich " : (($op->billing_period == 1) ? "Monatlich" : $op->billing_period."-monatlich")) ))?> | termination->building->networksection_id) ? $op->termination->building->networksection->name : "",0,24))?> | EUR price_nne?> + +----------------------------------------------------------------------------------------------------------------------- + + + + + diff --git a/Layout/andom-tec/menu.php b/Layout/andom-tec/menu.php index 3f322d5ed..b0400315c 100644 --- a/Layout/andom-tec/menu.php +++ b/Layout/andom-tec/menu.php @@ -18,23 +18,33 @@
  • "> News
  • + + is(["Admin", "netowner"])): ?>
  • Stammdaten
  • @@ -66,8 +76,7 @@ - - is(["Admin","salespartner"])): ?> + + is(["Admin","netowner","salespartner"])): ?>
  • Verkauf
  • @@ -100,7 +111,7 @@ diff --git a/Layout/andom-tec/menu_old.php b/Layout/andom-tec/menu_old.php new file mode 100644 index 000000000..3f322d5ed --- /dev/null +++ b/Layout/andom-tec/menu_old.php @@ -0,0 +1,117 @@ +
    +
    + + +
    + +
    + \ No newline at end of file diff --git a/Layout/default/Address/Form.php b/Layout/default/Address/Form.php index 0ad49b7ba..4ebf5f683 100644 --- a/Layout/default/Address/Form.php +++ b/Layout/default/Address/Form.php @@ -161,7 +161,7 @@
    @@ -262,7 +262,7 @@ - links)): ?> + links) && count($address->links) && array_key_exists($type, $address->links)): ?> links[$type] as $link): ?> diff --git a/Layout/default/Address/Index.php b/Layout/default/Address/Index.php index ac44e9cfd..054bc5db5 100644 --- a/Layout/default/Address/Index.php +++ b/Layout/default/Address/Index.php @@ -181,11 +181,13 @@ - customer_number?> - spin) ? "
    ".$address->spin."" : ""?> + $address->id, 'filter' => $filter, 's' => $pagination['start']])?>"> + customer_number?> + spin) ? "
    ".$address->spin."" : ""?> +
    - company)?> - getFullName()?> + $address->id, 'filter' => $filter, 's' => $pagination['start']])?>">company)?> + $address->id, 'filter' => $filter, 's' => $pagination['start']])?>">getFullName()?> street?>
    zip?> city?> diff --git a/Layout/default/Address/View.php b/Layout/default/Address/View.php index 320917bb2..db316cd22 100644 --- a/Layout/default/Address/View.php +++ b/Layout/default/Address/View.php @@ -29,7 +29,7 @@
    -

    Person/Firma

    +

    getCompanyOrName()?>customer_number) ? " [".$address->customer_number."]" : ""?>

    @@ -129,8 +129,7 @@ - - + @@ -142,8 +141,7 @@ - - + @@ -168,7 +166,7 @@ linked_as)): ?> linked_as[$type] as $link): ?> - + @@ -182,6 +180,49 @@ + contracts) && count($address->contracts)): ?> +
    +
    +

    Verträge

    + +
    Typ FirmaVornameNachnameName Telefon Mobil Email
    $link->address_id])?>">address->company?> $link->address_id])?>">address->firstname?>address->lastname?> $link->address_id])?>">address->getFullName()?> address->phone?> address->mobile?> address->email?>
    für: für: $link->origin_address_id])?>">origin->getCompanyOrName()?>origin->customer_number) ? " [".$link->origin->customer_number."]" : ""?>
    + + + + + + + + + + + contracts as $contract): ?> + + + + + + + + + + + +
    RolleContract IDProduktMatchcodeBestelldatumFertigstellungKündigung
    "> + $contract->id])?>"> + owner_id == $address->id): ?> + Vertragsinhaber + billingaddress_id == $address->id): ?> + Rechnungsempfänger + + + "> $contract->id])?>">id?>"> $contract->id])?>">product_name?>"> $contract->id])?>">matchcode?>">order_date) ? date('d.m.Y', $contract->order_date) : ""?>">finish_date) ? date('d.m.Y', $contract->finish_date) : ""?>">cancel_date) ? date('d.m.Y', $contract->cancel_date) : ""?> + $contract->id])?>" onclick="if(!confirm('Verknüpfung wirklich entfernen?')) return false;" class="text-danger" title="Verknüpfung entfernen"> +
    +
    +
    + +
    $filter, 's' => $s])?>" class="btn btn-secondary mr-1"> Zurück zur Übersicht diff --git a/Layout/default/AddressDB/Form.php b/Layout/default/AddressDB/Form.php new file mode 100644 index 000000000..19aa196ba --- /dev/null +++ b/Layout/default/AddressDB/Form.php @@ -0,0 +1,296 @@ +netzgebiet_id, $my_adb_networks)) { + $this->setFlash("Keine Berechtigung", "error"); + mfBaseController::redirect("AddressDB"); + } + +?> + + +
    +
    +
    +
    + +
    +

    Adresse

    +
    +
    +
    + + +
    +
    + +
    +
    +

    id) ? "Adresse bearbeiten" : "Neue Adresse"?>

    + +
    +
    +
    + + + + + + + + + + + +
    + +
    + + + + + +
    +
    + +
    + +
    + + + + + +
    +
    + +
    + +
    + + + + + +
    +
    + +
    + +
    + +
    + +
    +
    + + + +
    + +
    + + + + + +
    +
    + +
    + +
    + + + + + +
    +
    + +
    + +
    + + + + + +
    +
    + +
    + +
    + + + + + +
    +
    + +
    + +
    + + + + + +
    +
    + +
    + +
    + + + + + +
    +
    + +
    + +
    + + + + + +
    +
    + +
    + +
    + + + + + +
    +
    + +
    + +
    + +
    + + + + + +
    +
    + +
    + +
    + + + + + +
    +
    + +
    + +
    + +
    +
    + + id): ?> +
    + +
    + +
    + + + + + +
    +
    + + +
    +
    + + + +
    + +
    + +
    +
    + + + +
    +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/Layout/default/AddressDB/Index.php b/Layout/default/AddressDB/Index.php new file mode 100644 index 000000000..7fbdb49c5 --- /dev/null +++ b/Layout/default/AddressDB/Index.php @@ -0,0 +1,216 @@ +getUrl($Mod,"Index"); + $pagination_baseurl_params = ["filter" => $filter]; + $pagination_entity_name = "Adressen"; +?> + + + +
    +
    +
    +
    + +
    +

    GWR / AddressDB

    +
    +
    +
    + + +
    +
    + +
    +
    +

    Filter

    + +
    "> +
    + +
    + + +
    + + +
    + + +
    + +
    +
    " id="filter-gemeinde-id"> + + +
    +
    " id="filter-gemeinde-text"> + + +
    +
    + +
    +
    " id="filter-ortschaft-id"> + + +
    +
    " id="filter-ortschaft-text"> + + +
    +
    + +
    + + +
    +
    + +
    +
    + + +
    + +
    + + +
    + + + +
    + + +
    + +
    + + +
    + +
    + + +
    + + + +
    +
    +
    + + ">Filter zurücksetzen + +
    +
    +
    + +
    +
    + + + + +
    +
    +
    +

    Liste aller GWR-Adressen

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NetzgebietAdrcdOAIDextrefPLZGemeindeOrtschaftStraßeHausnummerWohneinheitenRollout JahrRollout Info
    netzgebiet->name?>adrcd?>oaid?>extref?>plz->plz?>ortschaft->gemeinde->name?>ortschaft->name?>strasse->name?>hausnummer?>wohneinheiten)?>rollout?>rollout_info?> + $address->id])?>"> +
    + + + + +
    +
    + +
    +
    + + + diff --git a/Layout/default/AddressDB/export.csv.php b/Layout/default/AddressDB/export.csv.php new file mode 100644 index 000000000..c6f3f7979 --- /dev/null +++ b/Layout/default/AddressDB/export.csv.php @@ -0,0 +1,31 @@ + +AddressDB_ID;Extref;Adrcd;OAID;Netzgebiet_Extref;Netzgebiet;GKZ;Gemeinde;OKZ;Ortschaft;PLZ;SKZ;Strasse;Hausnummer;Grundstueck;GPS Breite; GPS Laenge;Rollout;Rollout_Info;Freigabe;Nutzungseinheiten +netzgebiet_id); + $strasse = Layout::getMfValuecacheObject("ADBStrasse", $data->strasse_id); + $gemeinde = Layout::getMfValuecacheObject("ADBGemeinde",$strasse->gemeinde_id); + $ortschaft = Layout::getMfValuecacheObject("ADBOrtschaft", $data->ortschaft_id); + $plz = Layout::getMfValuecacheObject("ADBPlz", $data->plz_id); + $freigabe_array = json_decode($data->freigabe); + if(is_array($freigabe_array)) { + $freigabe = join(", ", $freigabe_array); + } else { + $freigabe = ""; + } + $unit_count = $data->unit_count; +?> +id?>;"extref?>";adrcd?>;"oaid?>";"extref?>";"name?>";kennziffer?>;"name?>";kennziffer?>;"name?>";"plz?>";kennziffer?>;"name?>";"hausnummer?>";"grund_nr?>";gps_lat?>;gps_long?>;rollout?>;"rollout_info?>";"";; + + + +
    +
    +
    +
    + +
    +

    Admin

    +
    +
    +
    + + +

    Secret Admin functions

    + + + + + \ No newline at end of file diff --git a/Layout/default/Building/Form.php b/Layout/default/Building/Form.php index 3ae8672cb..88d218bc7 100644 --- a/Layout/default/Building/Form.php +++ b/Layout/default/Building/Form.php @@ -136,14 +136,14 @@
    - +
    gps_lat) ? "readonly='readonly'" : ""?> />
    - +
    gps_lat) ? "readonly='readonly'" : ""?> />
    diff --git a/Layout/default/Building/Index.php b/Layout/default/Building/Index.php index 74d2edf34..f744a5ff9 100644 --- a/Layout/default/Building/Index.php +++ b/Layout/default/Building/Index.php @@ -384,9 +384,13 @@ accessToken: '' }).addTo(buildingMap); + L.MakiMarkers.accessToken = ''; + addMarkers(); } + + function addMarkers() { if(!Array.isArray(buildings) | !buildings.length) { return false; @@ -399,7 +403,36 @@ } var gps = [building.gps_lat, building.gps_long]; all_coords.push(gps); - var marker = L.marker(gps).addTo(buildingMap); + + var icon_color = "#CB2B3E"; + var icon_name = "home"; + + if(building.status == "connected") { + icon_color = "#2AAD27"; + } else if(building.status == "pipework-done") { + icon_color = "#CB8427"; + } + + if(building.type.match(/^(Zwei)/i)) { + icon_name = "town"; + } else if(building.type.match(/^(Mehr)/i)) { + icon_name = "city"; + } else if(building.type.match(/^(Unternehmen)/i)) { + icon_name = "industry"; + } else if(building.type.match(/^(Sender)/i)) { + icon_name = "communications-tower"; + } + + var marker_popup_content = ''; + + [["street", building.street], ["zip", building.zip], ["city", building.city], ["type", building.type], ["code", building.code], ["popname", building.popname], ["gps", building.gps_lat + ", " + building.gps_long], + ["contact", building.contact], ["phone", building.phone], ["email", building.email] + ].forEach(function(item) { + marker_popup_content = marker_popup_content.replaceAll("{{" + item[0].toUpperCase() + "}}", item[1]); + }); + + var icon = L.MakiMarkers.icon({icon: icon_name, color: icon_color, size: "l"}); + var marker = L.marker(gps, {icon: icon}).addTo(buildingMap).bindPopup(marker_popup_content); markers[building.id] = marker; }); diff --git a/Layout/default/Building/include/building_popup.php b/Layout/default/Building/include/building_popup.php new file mode 100644 index 000000000..f54aac585 --- /dev/null +++ b/Layout/default/Building/include/building_popup.php @@ -0,0 +1,36 @@ + +
    + {{STREET}}
    + {{ZIP}} {{CITY}} +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Objekt-ID:{{CODE}}
    Gebäudetyp:{{TYPE}}
    POP:{{POPNAME}}
    GPS:{{GPS}}
    Kontakt:{{CONTACT}}
    Telefon:{{PHONE}}
    Email:{{EMAIL}}
    + \ No newline at end of file diff --git a/Layout/default/Contract/Form.php b/Layout/default/Contract/Form.php index 201cea374..3018db6d1 100644 --- a/Layout/default/Contract/Form.php +++ b/Layout/default/Contract/Form.php @@ -1,3 +1,13 @@ +
    @@ -23,11 +33,15 @@

    id) ? "Vertrag bearbeiten" : "Neuer Vertrag"?>

    -
    "> +
    - + + + + +
    @@ -64,6 +78,19 @@
    +
    + +
    + +
    +
    + +
    @@ -95,7 +122,7 @@
    - +
    @@ -115,7 +142,7 @@
    - @@ -134,14 +161,14 @@
    - + finish_date) : ""?>">
    - + cancel_date) : ""?>">
    @@ -159,30 +186,31 @@
    @@ -240,7 +268,7 @@ * customer autocomplete */ // kunde - owner_id && is_object(($contract->owner))): ?> + owner_id && is_object($contract->owner)): ?> $('#owner_id').autoComplete('set', { value: owner_id?>, text: 'owner_id) ? str_replace("'", "\\'", str_replace(["\n", "\r"], " ", $contract->owner->getCompanyOrName()))." (".$contract->owner->zip." ".$contract->owner->city.", ".$contract->owner->street.")".(($contract->owner->customer_number) ? " [".$contract->owner->customer_number."]" : "") : ""?>'}); $('#owner_id').autoComplete(); @@ -396,7 +424,7 @@ \ \
    \ - \ \ \
    \ diff --git a/Layout/default/Contract/Index.php b/Layout/default/Contract/Index.php index 01efd0fda..93d6c9dca 100644 --- a/Layout/default/Contract/Index.php +++ b/Layout/default/Contract/Index.php @@ -12,10 +12,10 @@
    -

    Verträge

    +

    Aktive Produkte

    @@ -28,11 +28,16 @@

    Filter

    - "> + ">
    - + + +
    + +
    +
    @@ -51,12 +56,19 @@
    +
    + + +
    +
    +
    +
    + +

    Aktives Produkt

    +
    +
    +
    + + +
    +
    + + + +
    +
    +

    product_name?> (id?>)

    + + + + + + + + + + + + + + + + + +
    Matchcode:matchcode?>
    Vertragsinhaber: $contract->owner->id])?>">owner->getCompanyOrName()?> (owner->customer_number?>)
    Produkt:product_name?> [product_id?>]product_name != $contract->product->name) ? " (".$contract->product->name.")" : ""?>
    Produkt Info:product_info?>
    + +
    +
    + + +
    +
    +

    Neuer Contract

    + + "> + + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + + Eindeutige Identifizierung das Produkts. Z.B. Anschlussadresse, Domainname usw. +
    +
    + + product->attributes) && count($contract->product->attributes)) + && (array_key_exists(TT_ATTRIB_TERMINATION_REQUIRED_NAME, $contract->product->attributes) + && $contract->product->attributes[TT_ATTRIB_TERMINATION_REQUIRED_NAME]->value == 1) + || $contract->termination_id + ): ?> +
    + + + +
    + +
    + + Scheint statt dem echten Produktnamen auf der Rechnung auf +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + + + linkFrom) && count($contract->linkFrom)) || (is_array($contract->linkTo) && count($contract->linkTo))): ?> +

    Verknüpfte Verträge

    + + + + + + + + + + + + + + links as $link): ?> + contract_id == $contract->id) { + $linkcontract = $link->origin; + } else { + $linkcontract = $link->contract; + + } + + ?> + + + + + + + + + + + + +
    ÜbernehmenKündigenKundeContract IDProduktMatchcodeBestelldatumFertigstellungKündigung
    cancel_date && $linkcontract->cancel_date < date('U')) ? "" : "checked='checked'"?> /> $linkcontract->owner_id])?>" target="_blank">owner->getCompanyOrName()?>"> $linkcontract->id])?>" target="_blank">id?>"> $linkcontract->id])?>" target="_blank">product_name?>"> $linkcontract->id])?>" target="_blank">matchcode?>">order_date) ? date('d.m.Y', $linkcontract->order_date) : ""?>">finish_date) ? date('d.m.Y', $linkcontract->finish_date) : ""?>">cancel_date) ? date('d.m.Y', $linkcontract->cancel_date) : ""?>
    + + + + + +
    + +
    + +
    +
    + +
    +
    + + + + +
    +
    + +
    +
    + + + +
    +
    + + + + + +
    +
    + + + + + \ No newline at end of file diff --git a/Layout/default/Contract/View.php b/Layout/default/Contract/View.php new file mode 100644 index 000000000..c0d242cf2 --- /dev/null +++ b/Layout/default/Contract/View.php @@ -0,0 +1,282 @@ + + + +
    +
    +
    +
    + +
    +

    Aktives Produkt

    +
    +
    +
    + + +
    +
    + + + +
    +
    + finish_date || $contract->finish_date > date('U')): ?> +

    In Herstellung

    + + isCancelled()): ?> +

    GEKÜNDIGT

    + +

    ">product_name?> [id?>]

    + + + + + + + + upgradeFrom) && count($contract->upgradeFrom)): ?> + + + + + + upgradeTo) && count($contract->upgradeTo)): ?> + + + + + + + + downgradeFrom) && count($contract->downgradeFrom)): ?> + + + + + + downgradeTo) && count($contract->downgradeTo)): ?> + + + + + + + + productchangeFrom) && count($contract->productchangeFrom)): ?> + + + + + + productchangeTo) && count($contract->productchangeTo)): ?> + + + + + + + + relocationFrom) && count($contract->relocationFrom)): ?> + + + + + + relocationTo) && count($contract->relocationTo)): ?> + + + + + + + + + + billingaddress_id): ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Matchcode:matchcode?>
    Upgrade von: + upgradeFrom as $link): ?> + $link->origin_contract_id])?>" class="contract-link origin->cancel_date && $link->origin->cancel_date <= date('U')) ? "canceled" : ""?>">origin->product_name?> [origin->matchcode?>] (origin_contract_id?>)
    + +
    Upgrade auf: + upgradeTo as $link): ?> + $link->contract_id])?>" class="contract-link contract->cancel_date && $link->contract->cancel_date <= date('U')) ? "canceled" : ""?>">contract->product_name?> [contract->matchcode?>] (contract_id?>)
    + +
    Downgrade von: + downgradeFrom as $link): ?> + $link->origin_contract_id])?>" class="contract-link origin->cancel_date <= date('U')) ? "canceled" : ""?>">origin->product_name?> [origin->matchcode?>] (origin_contract_id?>)
    + +
    Downgrade auf: + downgradeTo as $link): ?> + $link->contract_id])?>" class="contract-link contract->cancel_date && $link->contract->cancel_date <= date('U')) ? "canceled" : ""?>">contract->product_name?> [contract->matchcode?>] (contract_id?>)
    + +
    Produktwechsel von: + productchangeFrom as $link): ?> + $link->origin_contract_id])?>" class="contract-link origin->cancel_date <= date('U')) ? "canceled" : ""?>">origin->product_name?> [origin->matchcode?>] (origin_contract_id?>)
    + +
    Produktwechsel auf: + productchangeTo as $link): ?> + $link->contract_id])?>" class="contract-link contract->cancel_date && $link->contract->cancel_date <= date('U')) ? "canceled" : ""?>">contract->product_name?> [contract->matchcode?>] (contract_id?>)
    + +
    Umzug von: + relocationFrom as $link): ?> + $link->origin_contract_id])?>" class="contract-link origin->cancel_date && $link->origin->cancel_date <= date('U')) ? "canceled" : ""?>">origin->product_name?> [origin->matchcode?>] (origin_contract_id?>)
    + +
    Umzug auf: + relocationTo as $link): ?> + $link->contract_id])?>" class="contract-link contract->cancel_date && $link->contract->cancel_date <= date('U')) ? "canceled" : ""?>">contract->product_name?> [contract->matchcode?>] (contract_id?>)
    + +
    Vertragsinhaber: $contract->owner_id])?>">owner->getCompanyOrName()?> [owner->customer_number?>]
    Rechnungsempfänger: $contract->billingaddress_id])?>">billingaddress->getCompanyOrName()?> [billingaddress->customer_number?>]
    Produkt:product_name?> [product_id?>]product_name != $contract->product->name) ? " (".$contract->product->name.")" : ""?>
    Produkt Info:product_info?>
    SLA:sla->name?>
    Externes Produkt:product_external) ? "Ja" : "Nein"?>
    Setup Preis:price_setup?>
    Preis Periodisch:price?>
    Verrechnungsperiode: + billing_period == 1) ? "Monatlich" : ""?> + billing_period == 12) ? "Jährlich" : ""?> + billing_period == 24) ? "Zweijährlich" : ""?> + billing_period == 36) ? "Dreijährlich" : ""?> +
    Verrechnungsstart Verzögerung:billing_delay?> Monate
    Bestelldatum:order_date) ? date('d.m.Y',$contract->order_date) : ""?>
    Fertigstellungsdatum: + finish_date) ? date('d.m.Y',$contract->finish_date) : ""?> + finish_date_by) ? "(".$contract->finisher->name.")" : ""?> +
    Kündigungsdatum: + cancel_date) ? date('d.m.Y',$contract->cancel_date) : ""?> + cancel_date_by) ? "(".$contract->canceler->name.")" : ""?> +
    Erstellt:create)?> (creator->name?>)
    Zuletzt bearbeitet:edit)?> (editor->name?>)
    + $contract->id])?>"> + finish_date && $contract->finish_date < date('U')): ?> + + $contract->id])?>"> + + + $contract->id])?>" onclick="if(!confirm('Jetzt fertigstellen und in Verrechnung geben?')) return false"> + +
    + +
    +
    + + linkFrom) && count($contract->linkFrom)) || (is_array($contract->linkTo) && count($contract->linkTo))): ?> +
    +
    +

    Verknüpfte Verträge $contract->id])?>">Neuen Contract anlegen

    + + + + + + + + + + + + + + links as $link): ?> + contract_id == $contract->id) { + $direction = "von"; + $linkcontract = $link->origin; + } else { + $linkcontract = $link->contract; + if($link->type == "upgrade" || $link->type == "downgrade") { + $direction = "auf"; + } + if($link->type == "relocation") { + $direction = "nach"; + } + + } + + ?> + + + + + + + + + + + + +
    KundeContract IDTypProduktMatchcodeBestelldatumFertigstellungKündigung
    $linkcontract->owner_id])?>">owner->getCompanyOrName()?>"> $linkcontract->id])?>">id?>">type, "contract")?> type != "link") ? $direction : ""?>"> $linkcontract->id])?>">product_name?>"> $linkcontract->id])?>">matchcode?>">order_date) ? date('d.m.Y', $linkcontract->order_date) : ""?>">finish_date) ? date('d.m.Y', $linkcontract->finish_date) : ""?>">cancel_date) ? date('d.m.Y', $linkcontract->cancel_date) : ""?> + $link->id])?>" onclick="if(!confirm('Verknüpfung wirklich entfernen?')) return false;" class="text-danger" title="Verknüpfung entfernen"> +
    +
    +
    + + + + +
    +
    + + \ No newline at end of file diff --git a/Layout/default/Contractconfig/Form.php b/Layout/default/Contractconfig/Form.php new file mode 100644 index 000000000..6778e84b8 --- /dev/null +++ b/Layout/default/Contractconfig/Form.php @@ -0,0 +1,108 @@ + + + +
    +
    +
    + +

    Aktives Produkt

    +
    +
    +
    + + +
    +
    + + + +
    +
    +

    product_name?> (id?>)

    + + + + + + + + + + + + + + + + + +
    Matchcode:matchcode?>
    Vertragsinhaber: $contract->owner->id])?>">owner->getCompanyOrName()?> (owner->customer_number?>)
    Produkt:product_name?>
    Produkt Info:product_info?>
    + +
    +
    + + +
    +
    +

    Konfiguration bearbeiten

    + +
    "> + + + + + + + items as $item): ?> + + + + + + +

    name?>

    +
    displayname?>: + type == "enum"): ?> + + + " name="itemvalues[id?>]" value="itemvalues[$item->id] : $item->getValue()?>" /> + + description?> +
    + + +
    +
    + +
    +
    +
    + +
    +
    + + + +
    +
    + + \ No newline at end of file diff --git a/Layout/default/Contractconfig/Index.php b/Layout/default/Contractconfig/Index.php deleted file mode 100644 index 7847ae08e..000000000 --- a/Layout/default/Contractconfig/Index.php +++ /dev/null @@ -1,124 +0,0 @@ - - - - -
    -
    -
    -
    - -
    -

    Vertragsconfig

    -
    -
    -
    - - - -
    -
    -
    -
    - - - -

    Gruppe name?>

    -
    "> - - items) && count($group->items)): ?> - items as $item): ?> - -
    -
    - - -
    "> - -
    -
    -
    - - -
    -
    -
    -
    - - -
    -
    - -
    -
    - - - -
    -
    - -
    -
    -
    -
    - - -
    -
    -
    -
    - - -
    -
    - -
    -
    - - -
    -
    -
    -
    -
    -
    - - - - - - - Keine Vertragsconfig Gruppen gefunden - -
    - -
    -
    -
    - - - - + + + +
    +
    +
    +
    + +
    +

    Contractconfig

    +
    +
    +
    + + + +
    +
    +
    +
    + +
    +
    +
    + "> + +
    + +
    + +
    +
    + +
    + + +
    +
    + + + +

    Gruppe name?> Neues Element erstellen

    + + + + items) && count($group->items)): ?> + items as $item): ?> + +
    + name?> - displayname?> [type?>] + + + +
    + + + + + + Keine Configgruppen gefunden + + + +
    + +
    +
    +
    + + + + + + + +
    +
    +
    +
    + +
    +

    Contractconfig

    +
    +
    +
    + + + +
    +
    +
    +
    + +
    +
    +
    +
    "> + +
    + +
    + +
    +
    +
    +
    + + +
    +
    + + + +

    Gruppe name?> Neues Element erstellen

    + + + + items) && count($group->items)): ?> + items as $item): ?> + +
    + name?> - displayname?> [type?>] + + + +
    + + + + + + Keine Configgruppen gefunden + + + +
    + +
    +
    +
    + + + + - + - + - + - +
    Kundennummer:customer_number?>customer_number?>
    Vertrag erfasst am:create)?>create)?>
    Bestelldatum:order_date)?>order_date)?>
    @@ -85,14 +85,14 @@ Rechnungsauskünfte, etc) nach Ihrem persönlichen Service-PIN fragen.

    -
    +

    Sollten Sie noch Fragen haben erreichen Sie uns per Mail (office@xinon.at) oder - telefonisch unter der Rufnummer 03115 40800.

    + telefonisch unter der Rufnummer 03115 40800.

    -
    +

    Mit besten Grüßen,

    diff --git a/Layout/default/Linework/Index.php b/Layout/default/Linework/Index.php index de06e26fc..7adee780d 100644 --- a/Layout/default/Linework/Index.php +++ b/Layout/default/Linework/Index.php @@ -302,29 +302,36 @@ building->getWorkflowvalue('ist_rohrverband_name')) ? $term->building->getWorkflowvalue('ist_rohrverband_name') : $term->building->getWorkflowvalue('rohrverband_name')?> building->getWorkflowvalue('ist_rohrtype')) ? $term->building->getWorkflowvalue('ist_rohrtype') : $term->building->getWorkflowvalue('rohrtype')?> - building->getWorkflowvalue('ist_rohrfarbe')): ?> + building->getWorkflowvalue('ist_rohrfarbe')) { + $rohrfarbe = $term->building->getWorkflowvalue('ist_rohrfarbe'); + } elseif($term->building->getWorkflowvalue('rohrfarbe')) { + $rohrfarbe = $term->building->getWorkflowvalue('rohrfarbe'); + } + ?> + + ; - building->getWorkflowvalue('ist_rohrfarbe')]["mark"]): ?> - color: #building->getWorkflowvalue('ist_rohrfarbe')]["hexfg"]?>; - - color: #building->getWorkflowvalue('ist_rohrfarbe')]["hex"]?>; - + background: rgb(,,); + background: linear-gradient(90deg, rgba(,,,.5) 0%, rgba(,,,.5) 50%, rgba(,,,.5) 50%, rgba(,,,.5) 100%); + padding-right: 42px; border-radius: 3px; - ">------- building->getWorkflowvalue('ist_rohrfarbe'))?> - building->getWorkflowvalue('rohrfarbe')): ?> + ">  + + ; - building->getWorkflowvalue('rohrfarbe')]["mark"]): ?> - color: #building->getWorkflowvalue('rohrfarbe')]["hexfg"]?>; + background-color: #; + + color: #; - color: #building->getWorkflowvalue('rohrfarbe')]["hex"]?>; + color: #; border-radius: 3px; - ">------- building->getWorkflowvalue('rohrfarbe'))?> + ">------- + diff --git a/Layout/default/Order/Index.php b/Layout/default/Order/Index.php index 50fe54238..03310198a 100644 --- a/Layout/default/Order/Index.php +++ b/Layout/default/Order/Index.php @@ -50,7 +50,7 @@
    @@ -285,7 +285,19 @@
    ">Versandtermin: shippingdate) ? "".date("d.m.Y", $order->shippingdate)."" : "--.--.----"?>
    -
    ">Vorortinstallation: install_date) ? "".date("d.m.Y",$order->install_date)."" : "--.--.----"?>
    + install_date): ?> +
    + Vorortinstallation: install_date)?> +
    + install_products)): ?> +
    + Vorortinstallation: --.--.---- +
    + +
    + Vorortinstallation: --.--.---- +
    +
    @@ -302,7 +314,7 @@ - +
    @@ -625,7 +637,6 @@ - log->debug("blah: ".print_r($order->terminations[0]->workflowitems["customer_setup_date"]->value,true)); ?> " id="order-id?>"> customer_type == "business") ? "" : ""?> @@ -731,7 +742,22 @@
    value->value_string) ? "active" : ""?>">Leitungsbau Backbone: terminations) && $order->terminations[0]->workflowitems["backbone_setup_date"]->value->value_string) ? "".$order->terminations[0]->workflowitems["backbone_setup_date"]->value->value_string."" : "--.--.----"?>
    ">Leitungsbau Kunde: terminations) && $order->terminations[0]->getWorkflowvalue("customer_setup_date")) ? "".$order->terminations[0]->getWorkflowvalue("customer_setup_date")."" : "--.--.----"?>
    ">Versandtermin: shippingdate) ? "".date("d.m.Y", $order->shippingdate)."" : "--.--.----"?>
    -
    " id="order-install-date-id?>">Vorortinstallation: install_date) ? "".date("d.m.Y",$order->install_date)."" : "--.--.----"?>
    + + install_date): ?> +
    + Vorortinstallation: install_date)?> +
    + install_products)): ?> +
    + Vorortinstallation: --.--.---- +
    + +
    + Vorortinstallation: --.--.---- +
    + + +
    diff --git a/Layout/default/Preorder/Form.php b/Layout/default/Preorder/Form.php index 2d5ca6fd7..ec0d9107e 100644 --- a/Layout/default/Preorder/Form.php +++ b/Layout/default/Preorder/Form.php @@ -7,7 +7,7 @@

    Vorbestellung

    @@ -47,18 +47,109 @@
    - +
    + +
    + -
    - + + + +
    +
    - + +
    + -
    + + + + + +
    +

    Vorbestellung & Produkt

    @@ -222,52 +319,90 @@
    - +
    - +
    - +
    - +
    - -
    - + +
    + +
    +
    + +
    +
    +
    + +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    - +
    - +
    - +
    - +
    @@ -293,9 +428,18 @@
    - - + + submit_type == "api" && $preorder->submit_request): ?> +
    +
    +
    + +
    +
    +
    +
    +
    @@ -334,7 +478,25 @@ $("#setup_product_id").val($("#setup-activation input.value").val()); } - + + $('#new_address_street').autoComplete({minLength: 2}).keydown(preventEnter).change(updateCustomerAddressFromNewAddress).on("autocomplete.select", updateCustomerAddressFromNewAddress); + $('#new_address_zip').autoComplete({minLength: 1}).keydown(preventEnter).change(updateCustomerAddressFromNewAddress).on("autocomplete.select", updateCustomerAddressFromNewAddress); + $('#new_address_city').autoComplete({minLength: 2}).keydown(preventEnter).change(updateCustomerAddressFromNewAddress).on("autocomplete.select", updateCustomerAddressFromNewAddress); + $('#new_address_district').autoComplete({minLength: 2}).keydown(preventEnter); + $('#new_address_housenumber').keydown(preventEnter).change(updateCustomerAddressFromNewAddress).on("autocomplete.select", updateCustomerAddressFromNewAddress); + $('#new_address_block').keydown(preventEnter); + $('#new_address_stiege').keydown(preventEnter); + $('#new_address_stock').keydown(preventEnter); + $('#new_address_tuer').keydown(preventEnter); + + + function preventEnter() { + if(event.keyCode == 13) { + event.preventDefault(); + return false; + } + } + $("#product_id").select2({ allowClear: true, @@ -363,12 +525,20 @@ $('#adb_hausnummer_id').select2({ ajax: { - url: ' "findAddress"])?>', + url: ' "findAddress", "campaign_id" => $campaign->id])?>', delay: 250, dataType: 'json' }, minimumInputLength: 3, - placeholder: "Suche nach Straße, Hausnummer, Ort" + placeholder: "Suche nach Straße, Hausnummer, Ort", + allowClear: true + }); + + $('#adb_hausnummer_id').on('select2:close', function(e) { + if(!$('#adb_hausnummer_id').val()) { + $('#new-address-toggle').show(); + } + }); @@ -376,6 +546,28 @@ var hausnummer_id = $('#adb_hausnummer_id').val(); if(!hausnummer_id) return; + $('#new-address-toggle').hide(); + $('#new-address').hide(); + + $.get('', + { + do: "getAddressByHousenumber", + hausnummer_id: hausnummer_id + }, + function(success) { + if(success.status != "OK") { + return; + } + var address = success.result; + console.log(address); + $('#new_address_street').val(address.strasse); + $('#new_address_housenumber').val(address.hausnummer); + $('#new_address_zip').val(address.plz); + $('#new_address_city').val(address.ort); + $('#new_address_district').val(address.ortschaft); + }, + 'json'); + $.get('', { @@ -434,6 +626,14 @@ "json"); }); + function updateCustomerAddressFromNewAddress() { + $('input[name=street]').val($('#new_address_street').val()); + $('input[name=housenumber]').val($('#new_address_housenumber').val()); + $('input[name=zip]').val($('#new_address_zip').val()); + $('input[name=city]').val($('#new_address_city').val()); + } + + $('#adb_wohneinheit_id').change(function() { val = $('#adb_wohneinheit_id').val(); @@ -558,6 +758,12 @@ 'json'); } + + function toggleNewAddress() { + $('#new-address').toggle(); + $('#wohneinheit_row').toggle(); + event.preventDefault(); + } \ No newline at end of file diff --git a/Layout/default/Preorder/Index.php b/Layout/default/Preorder/Index.php index 8c38f4545..e4a908838 100644 --- a/Layout/default/Preorder/Index.php +++ b/Layout/default/Preorder/Index.php @@ -16,7 +16,7 @@
    -

    Vorbestellungenname : ""?>

    +

    Vorbestellungenname : ""?>

    @@ -36,8 +36,8 @@
    @@ -61,6 +61,14 @@
    + +
    + + +
    @@ -72,6 +80,17 @@
    +
    +
    +
    + + +
    +
    @@ -94,7 +113,7 @@
    -

    Liste aller Vorbestellungenname : ""?>

    +

    Liste aller Vorbestellungenname : ""?>

    @@ -131,11 +150,12 @@ building_id): ?> building->street?>
    building->zip?> building->city?> adb_hausnummer_id): ?> - + address_created) ? "class='alert-warning' title='Manuell angelegt'" : ""?>"> adb_hausnummer->strasse->name?> adb_hausnummer->hausnummer?>
    adb_wohneinheit_id) ? ((string)$preorder->adb_wohneinheit ? $preorder->adb_wohneinheit."
    " : "") : "<keine Wohneinheit>
    "?> adb_hausnummer->plz->plz?> + adb_hausnummer->ortschaft->name?>
    adb_hausnummer->strasse->gemeinde->name?> @@ -144,7 +164,7 @@ connection_count) ? $preorder->connection_count : 1?> company) ? $preorder->company : $preorder->firstname." ".$preorder->lastname?>
    - street?>
    + street?>housenumber) ? " ".$preorder->housenumber : ""?>
    zip?> city?> diff --git a/Layout/default/Preordercampaign/Form.php b/Layout/default/Preordercampaign/Form.php index 569a6882a..5fba33ed1 100644 --- a/Layout/default/Preordercampaign/Form.php +++ b/Layout/default/Preordercampaign/Form.php @@ -122,6 +122,7 @@
    +
    @@ -142,6 +143,39 @@ Diese Felder müssen beim Bestellen angegeben werden
    + +
    + +
    + + Statt Ort muss Ortsteil/Bezirk angegeben werden +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + + Weiterer Bestellversuch liefert Fehler zurück +
    +
    +
    diff --git a/Layout/default/Preordercampaign/Index.php b/Layout/default/Preordercampaign/Index.php index addcbf490..c6dfdd29d 100644 --- a/Layout/default/Preordercampaign/Index.php +++ b/Layout/default/Preordercampaign/Index.php @@ -36,6 +36,18 @@
    + is("Admin")): ?> +
    + + +
    + +
    @@ -59,15 +71,15 @@
    - -

    Liste aller Vorbestellkampagnen

    @@ -102,15 +114,19 @@ ["preordercampaign_id" => $camp->id]])?>"> active_preorder_count?> homes_total): ?> - / homes_total?> (active_preorders) / $camp->homes_total) * 100, 2))?> %) + / homes_total?> (active_preorder_count / $camp->homes_total) * 100, 2))?> %) diff --git a/Layout/default/Preordercampaign/services.csv.php b/Layout/default/Preordercampaign/services.csv.php new file mode 100644 index 000000000..6603249c2 --- /dev/null +++ b/Layout/default/Preordercampaign/services.csv.php @@ -0,0 +1,8 @@ +name.'-'.date("Y-m-d_H-m-s").'.csv"'); +?> +Code;Gemeinde;PLZ;Ortschaft;Strasse;Hausnummer;Block;Stiege;Stock;Tuer;Adresszusatz;Adressinfo;Firma;UID;Vorname;Nachname;Kontakt Strasse;Kontakt PLZ;Kontakt Ort;Telefon;Email;Dienstleistung;Data + +"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"" + + + +
    +
    +
    +
    + +
    +

    id) ? "Emailaussendung bearbeiten" : "Neue Emailaussendung" ?>

    +
    +
    +
    + + +
    +
    + +
    +
    + +
    " enctype="multipart/form-data"> + +
    +
    + + + + +

    Absender

    + +
    + +
    + + Wird beim Empfänger als Absender angezeigt +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +

    Empfänger

    +

    Die Aussendung wird an die Kontaktemailadresse aller Bestellungen versendet. Wählen Sie folgende Konditionen aus, um die Empfänger zu beschränken:

    + +
    + +
    + +
    +
    + + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + + + + +
    + + +

    Email

    + +

    Im folgenden Editor können Sie ein HTML-Email verfassen. Verwenden Sie das Menü und die Werkzeugleiste um den Text zu formatieren.

    +
    + + +
    + + + +

    Dateianhänge

    +
    +
    +
    + + +
    +
    +
    + + files) && count($notification->files)): ?> +
    +
    +
    +
      + files as $file): ?> +
    • filename?>
    • + +
    +
    + +
    +
    + + +
    +
    + +
    +
    + +

    Versand

    +
    + +
    + + tosend_date) : ""?>" /> + Emailversand wird zu diesem Zeitpunkt gestartet +
    +
    + + +
    + +
    + +
    + +
    + +
    +
    +
    + +
    +
    + +
    + +
    + +
    +
    + +
    +
    + +
    +
    + + +
    +
    + +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    + +
    + + +
    +
    + + + + +
    +
    + +
    +
    + + + + + + \ No newline at end of file diff --git a/Layout/default/Preordernotification/Index.php b/Layout/default/Preordernotification/Index.php new file mode 100644 index 000000000..6e43b8ea0 --- /dev/null +++ b/Layout/default/Preordernotification/Index.php @@ -0,0 +1,123 @@ + + + +
    +
    +
    +
    + +
    +

    Emailaussendungen

    +
    +
    +
    + + +
    +
    + +
    +
    +

    Filter

    + +
    "> +
    + +
    + + +
    + + +
    + + +
    + +
    + + +
    + +
    + +
    +
    + + ">Filter zurücksetzen +
    +
    + + +
    +
    + + +
    +
    +
    +

    Liste offener Aussendungen

    +
    + + +
    from)?> to)?> - $camp->id])?>"> - $camp->id])?>" class="text-danger" onclick="if(!confirm('Vorbestellkampagne wirklich löschen?')) return false;" title="Vorbestellkampagne Löschen"> + $camp->id])?>" title="Bestellte Zusatzdienste exportieren"> + ["preordercampaign_id" => $camp->id]])?>" title="Email Aussendungen"> + is("Admin")): ?> + $camp->id])?>"> + $camp->id])?>" class="text-danger" onclick="if(!confirm('Vorbestellkampagne wirklich löschen?')) return false;" title="Vorbestellkampagne Löschen"> +
    + + + + + + + + + + + + + + + + + + + + + + +
    VersendetKampagneBetreffAnzahl EmpfängerGeplanter VersandBearbeitetErstellt
    + send_start && $notification->send_finish): ?> + + send_start && !$notification->send_finish): ?> + + send_start && !$notification->send_finish): ?> + + + sent_date) ? date('d.m.Y', $notification->sent_date) : ""?> + campaign->name?>subject?>recipient_count) ? $notification->recipient_count : ""?>tosend_date) ? date('d.m.Y', $notification->tosend_date) : "" ?>edit)?> (editor->name?>)create)?> (creator->name?>) + sent_date): ?> + $notification->id])?>"> + $notification->id])?>" class="text-danger" onclick="if(!confirm('Aussendung wirklich löschen?')) return false;" title="Aussendung Löschen"> + +
    +
    +
    + +
    +
    + + diff --git a/Layout/default/Product/Form.php b/Layout/default/Product/Form.php index 9d6458aff..4c0f007e5 100644 --- a/Layout/default/Product/Form.php +++ b/Layout/default/Product/Form.php @@ -114,7 +114,7 @@
    Name: Kundentyp: - RTR Code: + Beschreibung: Interne Notiz:
    diff --git a/Layout/default/Product/Index.php b/Layout/default/Product/Index.php index df377851b..1c6e080f1 100644 --- a/Layout/default/Product/Index.php +++ b/Layout/default/Product/Index.php @@ -24,6 +24,81 @@
    +
    +
    +

    Filter

    + +
    "> +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    +
    +
    + + ">Filter zurücksetzen +
    + +
    +
    + +
    +
    +
    @@ -34,8 +109,8 @@
    - - + + @@ -69,12 +144,17 @@
    - - + +
    + + diff --git a/Layout/default/Productgroup/Form.php b/Layout/default/Productgroup/Form.php new file mode 100644 index 000000000..b852db176 --- /dev/null +++ b/Layout/default/Productgroup/Form.php @@ -0,0 +1,78 @@ + + + +
    +
    +
    +
    + +
    +

    Productgruppen

    +
    +
    +
    + + +
    +
    + +
    +
    +

    id) ? "Produktgruppe bearbeiten" : "Neue Produktgruppe"?>

    + +
    "> +
    +
    + + + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    + +
    + +
    +
    + + + +
    +
    +
    + +
    +
    + + + \ No newline at end of file diff --git a/Layout/default/Productgroup/Index.php b/Layout/default/Productgroup/Index.php new file mode 100644 index 000000000..8f291d324 --- /dev/null +++ b/Layout/default/Productgroup/Index.php @@ -0,0 +1,68 @@ +getUrl($Mod,"Index"); + $pagination_baseurl_params = ["filter" => $filter]; + $pagination_entity_name = "Produktgruppen"; +?> + + + +
    +
    +
    +
    + +
    +

    Produkte

    +
    +
    +
    + + + + + diff --git a/Layout/default/Workflow/items/color.php b/Layout/default/Workflow/items/color.php index e5cec043f..094803bf5 100644 --- a/Layout/default/Workflow/items/color.php +++ b/Layout/default/Workflow/items/color.php @@ -11,14 +11,29 @@ if(preg_match('/^(.+)-1R$/', $color_name, $cmatch)) { diff --git a/Layout/default/footer.php b/Layout/default/footer.php index c2286a7b0..8727d9f2c 100644 --- a/Layout/default/footer.php +++ b/Layout/default/footer.php @@ -19,7 +19,8 @@ diff --git a/Layout/default/header.php b/Layout/default/header.php index a5645311a..ff7eb22c6 100644 --- a/Layout/default/header.php +++ b/Layout/default/header.php @@ -27,6 +27,7 @@ + diff --git a/Layout/default/menu.php b/Layout/default/menu.php index 4358e5304..c4609b6f1 100644 --- a/Layout/default/menu.php +++ b/Layout/default/menu.php @@ -18,27 +18,36 @@
  • "> News
  • + + is(["Admin", "netowner"])): ?>
  • Stammdaten
  • @@ -81,17 +90,18 @@ - - is(["Admin","salespartner"])): ?> + is(["Admin","netowner","salespartner"])): ?>
  • Verkauf
  • @@ -104,7 +114,7 @@ diff --git a/Layout/default/tpl/pagination.php b/Layout/default/tpl/pagination.php index 1bd0923b5..c15392242 100644 --- a/Layout/default/tpl/pagination.php +++ b/Layout/default/tpl/pagination.php @@ -53,7 +53,7 @@ if($mfPagination_pagecount < 12) { $mfPagination_baseurl_params['s'] = $i * $pagination['count']; if(($i == 0 || $i == $mfPagination_pagecount) || ($i >= $show_from && $i <= $show_to)) { - $log->debug("show_from: $show_from, show_to: $show_to"); + //$log->debug("show_from: $show_from, show_to: $show_to"); $page = [ 's' => $i * $pagination['count'], diff --git a/application/ADBGemeinde/ADBGemeinde.php b/application/ADBGemeinde/ADBGemeinde.php index a32bec397..6332bcb81 100644 --- a/application/ADBGemeinde/ADBGemeinde.php +++ b/application/ADBGemeinde/ADBGemeinde.php @@ -2,14 +2,13 @@ class ADBGemeinde extends mfBaseModel { public $plzs = []; - + private $ortschaften = []; protected function init() { $this->db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME); $this->table = "Gemeinde"; } - public function loadByGemeindeCode($code) { $res = $this->db->select("Gemeinde","*","code=$code"); if($this->db->num_rows($res)) { @@ -66,4 +65,35 @@ class ADBGemeinde extends mfBaseModel { } return $list; } + + public function getProperty($name) { + if($this->$name == null) { + + if(!$this->id) { + return null; + } + + if($name == "types") { + $this->loadAddresstypes(); + return $this->types; + } + + if($name == "ortschaften") { + $this->ortschaften = ADBOrtschaftModel::search(["gemeinde_id" => $this->id]); + return $this->ortschaften; + } + + $classname = ucfirst($name); + $idfield = $name."_id"; + $this->$name = new $classname($this->$idfield); + + if($this->$name->id) { + return $this->$name; + } else { + return null; + } + } + + return $this->$name; + } } diff --git a/application/ADBGemeinde/ADBGemeindeModel.php b/application/ADBGemeinde/ADBGemeindeModel.php index 3013c3ef8..378b8bc4a 100644 --- a/application/ADBGemeinde/ADBGemeindeModel.php +++ b/application/ADBGemeinde/ADBGemeindeModel.php @@ -40,7 +40,16 @@ class ADBGemeindeModel { $db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME); $where = self::getSqlFilter($filter); - $res = $db->select("Gemeinde", "*", "$where ORDER BY name,code,kennziffer LIMIT 1"); + $sql = "SELECT Gemeinde.* FROM Gemeinde + LEFT JOIN Plz ON (Plz.gemeinde_id = Gemeinde.id) + LEFT JOIN GemeindeNetzgebiet ON (GemeindeNetzgebiet.gemeinde_id = Gemeinde.id) + LEFT JOIN Netzgebiet ON (GemeindeNetzgebiet.netzgebiet_id = Netzgebiet.id) + LEFT JOIN Ortschaft ON (Ortschaft.gemeinde_id = Gemeinde.id) + WHERE $where + GROUP BY Gemeinde.id + ORDER BY name,code,kennziffer + LIMIT 1"; + $res = $db->query($sql); if($db->num_rows($res)) { $data = $db->fetch_object($res); $item = new ADBGemeinde($data); @@ -94,6 +103,7 @@ class ADBGemeindeModel { LEFT JOIN Plz ON (Plz.gemeinde_id = Gemeinde.id) LEFT JOIN GemeindeNetzgebiet ON (GemeindeNetzgebiet.gemeinde_id = Gemeinde.id) LEFT JOIN Netzgebiet ON (GemeindeNetzgebiet.netzgebiet_id = Netzgebiet.id) + LEFT JOIN Ortschaft ON (Ortschaft.gemeinde_id = Gemeinde.id) WHERE $where GROUP BY Gemeinde.id ORDER BY name,code,kennziffer"; @@ -126,6 +136,15 @@ class ADBGemeindeModel { $where .= " AND Netzgebiet.id=$netzgebiet_id"; } elseif(is_array($netzgebiet_id) && count($netzgebiet_id)) { $where .= " AND Netzgebiet.id IN (". implode(",", $netzgebiet_id).")"; + } elseif($netzgebiet_id === null) { + $where .= " AND Netzgebiet.id IS NULL"; + } + } + + if(array_key_exists("netzgebiet_extref", $filter)) { + $netzgebiet_extref = FronkDB::singleton()->escape($filter['netzgebiet_extref']); + if($netzgebiet_extref) { + $where .= " AND Netzgebiet.extref = '$netzgebiet_extref'"; } } @@ -157,7 +176,7 @@ class ADBGemeindeModel { if(array_key_exists("name%", $filter)) { $name = FronkDB::singleton()->escape($filter['name%']); if($name) { - $where .= " AND Gemeinde.`name` like '%$name%'"; + $where .= " AND Gemeinde.`name` like '$name%'"; } } @@ -171,7 +190,21 @@ class ADBGemeindeModel { if(array_key_exists("plz%", $filter)) { $plz = FronkDB::singleton()->escape($filter['plz%']); if($plz) { - $where .= " AND Plz.plzstring like '%$plz%'"; + $where .= " AND Plz.plzstring like '$plz%'"; + } + } + + if(array_key_exists("ortschaft", $filter)) { + $ortschaft = FronkDB::singleton()->escape($filter['ortschaft']); + if($ortschaft) { + $where .= " AND Plz.ortschaft = '$ortschaft'"; + } + } + + if(array_key_exists("ortschaft%", $filter)) { + $ortschaft = FronkDB::singleton()->escape($filter['ortschaft%']); + if($ortschaft) { + $where .= " AND Plz.ortschaft like '$ortschaft%'"; } } diff --git a/application/ADBHausnummer/ADBHausnummer.php b/application/ADBHausnummer/ADBHausnummer.php index bb2f9a829..284df5ae5 100644 --- a/application/ADBHausnummer/ADBHausnummer.php +++ b/application/ADBHausnummer/ADBHausnummer.php @@ -1,9 +1,12 @@ db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME); @@ -36,23 +39,87 @@ class ADBHausnummer extends mfBaseModel { return $data; }*/ + public function getNewOAID() { + if(!$this->plz_id) { + return false; + } + + $cc = "AT"; + $zip = $this->getProperty("plz")->plz; + + for($try = 16; $try > 0; $try--) { + $rnd[0] = random_int(0, 255); + $rnd[1] = random_int(0, 255); + $rnd[2] = random_int(0, 255); + $rnd[3] = random_int(0, 255); + + $code = "$cc-$zip-"; + foreach($rnd as $r) { + $code .= str_pad(dechex($r), 2, "0", STR_PAD_LEFT); + } + + if(ADBHausnummerModel::search(['oaid' => $code])) { + $this->log->warn(__FILE__."::getNewObjectCode: New Code already in use. Trying again for a maximum of $try times."); + } else { + // code is unique + break; + } + } + + if($try == 0) { + return null; + } + + return $code; + } + public function getProperty($name) { if($this->$name == null) { if($name == "freigaben") { - $this->freigaben = explode(",", $this->freigabe); + $this->freigaben = json_decode($this->freigabe); + if(!is_array($this->freigaben)) { + $this->freigaben = []; + } return $this->freigaben; } + if($name == "netzgebiet") { + $this->netzgebiet = new ADBNetzgebiet($this->netzgebiet_id); + return $this->netzgebiet; + } + + if($name == "ortschaft") { + $this->ortschaft = new ADBOrtschaft($this->ortschaft_id); + return $this->ortschaft; + } + if($name == "strasse") { $this->strasse = new ADBStrasse($this->strasse_id); return $this->strasse; } if($name == "plz") { - $this->plz = new ADBPlz($this->plz_id); + $this->plz = mfValuecache::singleton()->get("adbplz-".$this->plz_id); + if($this->plz === null) { + $this->plz = new ADBPlz($this->plz_id); + if($this->plz->id) { + mfValuecache::singleton()->set("adplz-".$this->plz_id, $this->plz); + } + } return $this->plz; } + + if($name == "wohneinheiten") { + $this->wohneinheiten = mfValuecache::singleton()->get("adbWohneinheiten-hausnummer-".$this->id); + if($this->wohneinheiten === null) { + $this->wohneinheiten = ADBWohneinheitModel::search(['hausnummer_id' => $this->id]); + if($this->wohneinheiten) { + mfValuecache::singleton()->set("adbWohneinheiten-hausnummer-".$this->id, $this->wohneinheiten); + } + } + return $this->wohneinheiten; + } $classname = ucfirst($name); $idfield = $name."_id"; diff --git a/application/ADBHausnummer/ADBHausnummerModel.php b/application/ADBHausnummer/ADBHausnummerModel.php index eb9abfee0..144ef2412 100644 --- a/application/ADBHausnummer/ADBHausnummerModel.php +++ b/application/ADBHausnummer/ADBHausnummerModel.php @@ -1,6 +1,8 @@ debug($where); + + $sql = "SELECT Hausnummer.* FROM Hausnummer + LEFT JOIN Ortschaft ON (Ortschaft.id = Hausnummer.ortschaft_id) + LEFT JOIN Gemeinde ON (Gemeinde.id = Ortschaft.gemeinde_id) + LEFT JOIN Strasse ON (Hausnummer.strasse_id = Strasse.id) + LEFT JOIN Plz ON (Hausnummer.plz_id = Plz.id) + WHERE $where + ORDER BY netzgebiet_id,Gemeinde.id,ortschaft_id,strasse_id,LENGTH(hausnummer), hausnummer + LIMIT 1"; + + //mfLoghandler::singleton()->debug($where); $res = $db->select("Hausnummer", "*", "$where ORDER BY strasse_id,hausnummer LIMIT 1"); if($db->num_rows($res)) { $data = $db->fetch_object($res); @@ -82,8 +102,13 @@ class ADBHausnummerModel { $where = self::getSqlFilter($filter); $sql = "SELECT COUNT(*) as cnt FROM Hausnummer + LEFT JOIN Ortschaft ON (Ortschaft.id = Hausnummer.ortschaft_id) + LEFT JOIN Gemeinde ON (Gemeinde.id = Ortschaft.gemeinde_id) + LEFT JOIN Strasse ON (Hausnummer.strasse_id = Strasse.id) + LEFT JOIN Plz ON (Hausnummer.plz_id = Plz.id) WHERE $where - "; + "; + $res = $db->query($sql); if($db->num_rows($res)) { @@ -93,14 +118,18 @@ class ADBHausnummerModel { return 0; } - public static function search($filter, $limit = false) { + public static function search($filter, $limit = false, $returnDBRessource = false) { $items = []; $db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME); $where = self::getSqlFilter($filter); $sql = "SELECT Hausnummer.* FROM Hausnummer + LEFT JOIN Ortschaft ON (Ortschaft.id = Hausnummer.ortschaft_id) + LEFT JOIN Gemeinde ON (Gemeinde.id = Ortschaft.gemeinde_id) + LEFT JOIN Strasse ON (Hausnummer.strasse_id = Strasse.id) + LEFT JOIN Plz ON (Hausnummer.plz_id = Plz.id) WHERE $where - ORDER BY strasse_id,hausnummer"; + ORDER BY netzgebiet_id,Gemeinde.id,ortschaft_id,strasse_id,LENGTH(hausnummer), hausnummer"; mfLoghandler::singleton()->debug($sql); if(is_array($limit) && count($limit)) { @@ -111,8 +140,16 @@ class ADBHausnummerModel { } } + mfLoghandler::singleton()->debug($sql); + $res = $db->query($sql); if($db->num_rows($res)) { + + // hack for AddressDBController::exportAction + if($returnDBRessource) { + return $res; + } + while($data = $db->fetch_object($res)) { $items[] = new ADBHausnummer($data); } @@ -123,6 +160,36 @@ class ADBHausnummerModel { private static function getSqlFilter($filter) { $where = "1=1 "; + if(array_key_exists("adrcd", $filter)) { + $adrcd = FronkDB::singleton()->escape($filter['adrcd']); + if($adrcd) { + $where .= " AND Hausnummer.`adrcd` = '$adrcd'"; + } + } + + if(array_key_exists("adrcd%", $filter)) { + $adrcd = FronkDB::singleton()->escape($filter['adrcd%']); + if($adrcd) { + $where .= " AND Hausnummer.`adrcd` like '$adrcd%'"; + } + } + + + if(array_key_exists("oaid", $filter)) { + $oaid = FronkDB::singleton()->escape($filter['oaid']); + if($oaid) { + $where .= " AND Hausnummer.`oaid` = '$oaid'"; + } + } + + if(array_key_exists("oaid%", $filter)) { + $oaid = FronkDB::singleton()->escape($filter['oaid%']); + if($oaid) { + $where .= " AND Hausnummer.`oaid` like '$oaid%'"; + } + } + + if(array_key_exists("extref", $filter)) { $extref = FronkDB::singleton()->escape($filter['extref']); if($extref) { @@ -130,12 +197,37 @@ class ADBHausnummerModel { } } + if(array_key_exists("extref%", $filter)) { + $extref = FronkDB::singleton()->escape($filter['extref%']); + if($extref) { + $where .= " AND Hausnummer.`extref` like '$extref%'"; + } + } + + + if(array_key_exists("plz", $filter)) { + $plz = FronkDB::singleton()->escape($filter['plz']); + if($plz) { + $where .= " AND Plz.plz = '$plz'"; + } + } + + if(array_key_exists("plz%", $filter)) { + $plz = FronkDB::singleton()->escape($filter['plz%']); + if($plz) { + $where .= " AND Plz.plz like '$plz%'"; + } + } + + if(array_key_exists("netzgebiet_id", $filter)) { $netzgebiet_id = $filter['netzgebiet_id']; if(is_numeric($netzgebiet_id)) { $where .= " AND Hausnummer.netzgebiet_id=$netzgebiet_id"; } elseif(is_array($netzgebiet_id) && count($netzgebiet_id)) { $where .= " AND Hausnummer.netzgebiet_id IN (". implode(",", $netzgebiet_id).")"; + } elseif($netzgebiet_id === null) { + $where .= " AND Hausnummer.netzgebiet_id IS NULL"; } } @@ -157,10 +249,61 @@ class ADBHausnummerModel { } } + if(array_key_exists("gemeinde_id", $filter)) { + $gemeinde_id = $filter['gemeinde_id']; + if(is_numeric($gemeinde_id)) { + $where .= " AND Ortschaft.gemeinde_id=$gemeinde_id"; + } elseif(is_array($gemeinde_id) && count($gemeinde_id)) { + $where .= " AND Ortschaft.gemeinde_id IN (". implode(",", $gemeinde_id).")"; + } + } + + if(array_key_exists("gemeinde", $filter)) { + $gemeinde = FronkDB::singleton()->escape($filter['gemeinde']); + if($gemeinde) { + $where .= " AND Gemeinde.name = '$gemeinde'"; + } + } + + if(array_key_exists("gemeinde%", $filter)) { + $gemeinde = FronkDB::singleton()->escape($filter['gemeinde%']); + if($gemeinde) { + $where .= " AND Gemeinde.name like '$gemeinde%'"; + } + } + + if(array_key_exists("ortschaft", $filter)) { + $ortschaft = FronkDB::singleton()->escape($filter['ortschaft']); + if($ortschaft) { + $where .= " AND Ortschaft.name = '$ortschaft'"; + } + } + + if(array_key_exists("ortschaft%", $filter)) { + $ortschaft = FronkDB::singleton()->escape($filter['ortschaft%']); + if($ortschaft) { + $where .= " AND Ortschaft.name like '$ortschaft%'"; + } + } + + if(array_key_exists("ortschaft_id", $filter)) { + $ortschaft_id = $filter['ortschaft_id']; + if(is_numeric($ortschaft_id)) { + $where .= " AND Hausnummer.ortschaft_id=$ortschaft_id"; + } elseif(is_array($ortschaft_id) && count($ortschaft_id)) { + $where .= " AND Hausnummer.ortschaft_id IN (". implode(",", $ortschaft_id).")"; + } + } + if(array_key_exists("hausnummer", $filter)) { - $hausnummer = FronkDB::singleton()->escape($filter['hausnummer']); - if($hausnummer) { - $where .= " AND Hausnummer.`hausnummer` = '$hausnummer'"; + if(is_array($filter['hausnummer'])) { + $hausnummer = $filter['hausnummer']; + $where .= " AND Hausnummer.`hausnummer` IN ('".implode("','", $hausnummer)."')"; + } else { + $hausnummer = FronkDB::singleton()->escape($filter['hausnummer']); + if($hausnummer) { + $where .= " AND Hausnummer.`hausnummer` = '$hausnummer'"; + } } } @@ -171,6 +314,48 @@ class ADBHausnummerModel { } } + if(array_key_exists("strasse", $filter)) { + $strasse = FronkDB::singleton()->escape($filter['strasse']); + if($strasse) { + $where .= " AND Strasse.name = '$strasse'"; + } + } + + if(array_key_exists("strasse%", $filter)) { + $strasse = FronkDB::singleton()->escape($filter['strasse%']); + if($strasse) { + $where .= " AND Strasse.name like '%$strasse%'"; + } + } + + if(array_key_exists("rollout", $filter)) { + $rollout = FronkDB::singleton()->escape($filter['rollout']); + if($rollout) { + $where .= " AND Hausnummer.rollout = '$rollout'"; + } + } + + if(array_key_exists("rollout%", $filter)) { + $rollout = FronkDB::singleton()->escape($filter['rollout%']); + if($rollout) { + $where .= " AND Hausnummer.rollout like '%$rollout%'"; + } + } + + if(array_key_exists("rollout_info", $filter)) { + $rollout_info = FronkDB::singleton()->escape($filter['rollout_info']); + if($rollout_info) { + $where .= " AND Hausnummer.rollout_info = '$rollout_info'"; + } + } + + if(array_key_exists("rollout_info%", $filter)) { + $rollout_info = FronkDB::singleton()->escape($filter['rollout_info%']); + if($rollout_info) { + $where .= " AND Hausnummer.rollout_info like '%$rollout_info%'"; + } + } + //var_dump($filter, $where);exit; return $where; } diff --git a/application/ADBNetzgebiet/ADBNetzgebietModel.php b/application/ADBNetzgebiet/ADBNetzgebietModel.php index a9ac527f7..569ea6f37 100644 --- a/application/ADBNetzgebiet/ADBNetzgebietModel.php +++ b/application/ADBNetzgebiet/ADBNetzgebietModel.php @@ -5,6 +5,7 @@ class ADBNetzgebietModel { public $extref; public $source; public $source_id; + public $freigabe; public $create = null; public $edit = null; @@ -90,9 +91,7 @@ class ADBNetzgebietModel { $where = self::getSqlFilter($filter); $sql = "SELECT Netzgebiet.* FROM Netzgebiet - LEFT JOIN Plz ON (Plz.netzgebiet_id = Netzgebiet.id) WHERE $where - GROUP BY Netzgebiet.id ORDER BY name"; mfLoghandler::singleton()->debug($sql); @@ -116,6 +115,15 @@ class ADBNetzgebietModel { private static function getSqlFilter($filter) { $where = "1=1 "; + if(array_key_exists("netzgebiet_id", $filter)) { + $netzgebiet_id = $filter['netzgebiet_id']; + if(is_numeric($netzgebiet_id)) { + $where .= " AND Netzgebiet.netzgebiet_id=$netzgebiet_id"; + } elseif(is_array($netzgebiet_id) && count($netzgebiet_id)) { + $where .= " AND Netzgebiet.id IN (". implode(",", $netzgebiet_id).")"; + } + } + if(array_key_exists("name", $filter)) { $name = FronkDB::singleton()->escape($filter['name']); if($name) { @@ -123,6 +131,13 @@ class ADBNetzgebietModel { } } + if(array_key_exists("name%", $filter)) { + $name = FronkDB::singleton()->escape($filter['name%']); + if($name) { + $where .= " AND Netzgebiet.`name` LIKE '$name%'"; + } + } + if(array_key_exists("extref", $filter)) { $extref = FronkDB::singleton()->escape($filter['extref']); if($extref) { diff --git a/application/ADBOrtschaft/ADBOrtschaft.php b/application/ADBOrtschaft/ADBOrtschaft.php index 9b0d77139..fdb1b48bf 100644 --- a/application/ADBOrtschaft/ADBOrtschaft.php +++ b/application/ADBOrtschaft/ADBOrtschaft.php @@ -31,7 +31,7 @@ class ADBOrtschaft extends mfBaseModel { if($this->$name == null) { if($name == "gemeinde") { - $this->gemeinde = new ADBGemeinde($this->hausnummer_id); + $this->gemeinde = new ADBGemeinde($this->gemeinde_id); return $this->gemeinde; } diff --git a/application/ADBOrtschaft/ADBOrtschaftModel.php b/application/ADBOrtschaft/ADBOrtschaftModel.php index 48bfc9a2c..cb55f2527 100644 --- a/application/ADBOrtschaft/ADBOrtschaftModel.php +++ b/application/ADBOrtschaft/ADBOrtschaftModel.php @@ -41,7 +41,16 @@ class ADBOrtschaftModel { $db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME); $where = self::getSqlFilter($filter); - $res = $db->select("Ortschaft", "*", "$where ORDER BY name,kennziffer LIMIT 1"); + $sql = "SELECT Ortschaft.* FROM Ortschaft + LEFT JOIN Gemeinde ON (Ortschaft.gemeinde_id = Gemeinde.id) + LEFT JOIN Plz ON (Plz.gemeinde_id = Gemeinde.id) + LEFT JOIN GemeindeNetzgebiet ON (GemeindeNetzgebiet.gemeinde_id = Gemeinde.id) + LEFT JOIN Netzgebiet ON (GemeindeNetzgebiet.netzgebiet_id = Netzgebiet.id) + WHERE $where + ORDER BY gemeinde_id,Ortschaft.name,Ortschaft.kennziffer + LIMIT 1"; + + $res = $db->query($sql); if($db->num_rows($res)) { $data = $db->fetch_object($res); $item = new ADBOrtschaft($data); @@ -92,10 +101,15 @@ class ADBOrtschaftModel { $where = self::getSqlFilter($filter); $sql = "SELECT Ortschaft.* FROM Ortschaft + LEFT JOIN Gemeinde ON (Ortschaft.gemeinde_id = Gemeinde.id) + LEFT JOIN Plz ON (Plz.gemeinde_id = Gemeinde.id) + LEFT JOIN GemeindeNetzgebiet ON (GemeindeNetzgebiet.gemeinde_id = Gemeinde.id) + LEFT JOIN Netzgebiet ON (GemeindeNetzgebiet.netzgebiet_id = Netzgebiet.id) WHERE $where - ORDER BY name,kennziffer"; + GROUP BY Ortschaft.id + ORDER BY Ortschaft.name,Ortschaft.kennziffer,gemeinde_id"; - //mfLoghandler::singleton()->debug($sql); + mfLoghandler::singleton()->debug($sql); if(is_array($limit) && count($limit)) { if(is_numeric($limit['start']) && is_numeric($limit['count'])) { $sql .= " LIMIT ".$limit['start'].", ".$limit['count']; @@ -116,6 +130,24 @@ class ADBOrtschaftModel { private static function getSqlFilter($filter) { $where = "1=1 "; + if(array_key_exists("netzgebiet_id", $filter)) { + $netzgebiet_id = $filter['netzgebiet_id']; + if(is_numeric($netzgebiet_id)) { + $where .= " AND Netzgebiet.id=$netzgebiet_id"; + } elseif(is_array($netzgebiet_id) && count($netzgebiet_id)) { + $where .= " AND Netzgebiet.id IN (". implode(",", $netzgebiet_id).")"; + } elseif($netzgebiet_id === null) { + $where .= " AND Netzgebiet.id IS NULL"; + } + } + + if(array_key_exists("netzgebiet_extref", $filter)) { + $netzgebiet_extref = FronkDB::singleton()->escape($filter['netzgebiet_extref']); + if($netzgebiet_extref) { + $where .= " AND Netzgebiet.extref = '$netzgebiet_extref'"; + } + } + if(array_key_exists("gemeinde_id", $filter)) { $gemeinde_id = $filter['gemeinde_id']; if(is_numeric($gemeinde_id)) { @@ -149,7 +181,21 @@ class ADBOrtschaftModel { if(array_key_exists("name%", $filter)) { $name = FronkDB::singleton()->escape($filter['name%']); if($name) { - $where .= " AND Ortschaft.`name` like '%$name%'"; + $where .= " AND Ortschaft.`name` like '$name%'"; + } + } + + if(array_key_exists("plz", $filter)) { + $plz = FronkDB::singleton()->escape($filter['plz']); + if($plz) { + $where .= " AND Plz.plzstring = '$plz'"; + } + } + + if(array_key_exists("plz%", $filter)) { + $plz = FronkDB::singleton()->escape($filter['plz%']); + if($plz) { + $where .= " AND Plz.plzstring like '$plz%'"; } } diff --git a/application/ADBPlz/ADBPlzModel.php b/application/ADBPlz/ADBPlzModel.php index db558f741..219432934 100644 --- a/application/ADBPlz/ADBPlzModel.php +++ b/application/ADBPlz/ADBPlzModel.php @@ -40,7 +40,16 @@ class ADBPlzModel { $db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME); $where = self::getSqlFilter($filter); - $res = $db->select("Plz", "*", "$where ORDER BY plz LIMIT 1"); + $sql = "SELECT Plz.* FROM Plz + LEFT JOIN Gemeinde ON (Gemeinde.id = Plz.gemeinde_id) + LEFT JOIN GemeindeNetzgebiet ON (GemeindeNetzgebiet.gemeinde_id = Plz.gemeinde_id) + LEFT JOIN Netzgebiet ON (GemeindeNetzgebiet.netzgebiet_id = Netzgebiet.id) + WHERE $where + GROUP BY Plz.id + ORDER BY plz + LIMIT 1"; + mfLoghandler::singleton()->debug($sql); + $res = $db->query($sql); if($db->num_rows($res)) { $data = $db->fetch_object($res); $item = new ADBPlz($data); @@ -119,7 +128,6 @@ class ADBPlzModel { private static function getSqlFilter($filter) { $where = "1=1 "; - if(array_key_exists("netzgebiet_id", $filter)) { $netzgebiet_id = $filter['netzgebiet_id']; if(is_numeric($netzgebiet_id)) { @@ -129,12 +137,19 @@ class ADBPlzModel { } } - if(array_key_exists("hausnummer_id", $filter)) { - $hausnummer_id = $filter['hausnummer_id']; - if(is_numeric($hausnummer_id)) { - $where .= " AND Plz.hausnummer_id=$hausnummer_id"; - } elseif(is_array($hausnummer_id) && count($hausnummer_id)) { - $where .= " AND Plz.hausnummer_id IN (". implode(",", $hausnummer_id).")"; + if(array_key_exists("netzgebiet_extref", $filter)) { + $netzgebiet_extref = FronkDB::singleton()->escape($filter['netzgebiet_extref']); + if($netzgebiet_extref) { + $where .= " AND Netzgebiet.extref = '$netzgebiet_extref'"; + } + } + + if(array_key_exists("gemeinde_id", $filter)) { + $gemeinde_id = $filter['gemeinde_id']; + if(is_numeric($gemeinde_id)) { + $where .= " AND Plz.gemeinde_id=$gemeinde_id"; + } elseif(is_array($gemeinde_id) && count($gemeinde_id)) { + $where .= " AND Plz.gemeinde_id IN (". implode(",", $gemeinde_id).")"; } } @@ -157,7 +172,7 @@ class ADBPlzModel { if(array_key_exists("plzstring%", $filter)) { $plzstring = FronkDB::singleton()->escape($filter['plzstring%']); if($plzstring) { - $where .= " AND Plz.`plzstring` like '%$plzstring%'"; + $where .= " AND Plz.`plzstring` like '$plzstring%'"; } } diff --git a/application/ADBStrasse/ADBStrasseModel.php b/application/ADBStrasse/ADBStrasseModel.php index 1419ad321..4a51a0fde 100644 --- a/application/ADBStrasse/ADBStrasseModel.php +++ b/application/ADBStrasse/ADBStrasseModel.php @@ -41,7 +41,17 @@ class ADBStrasseModel { $db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME); $where = self::getSqlFilter($filter); - $res = $db->select("Strasse", "*", "$where ORDER BY gemeinde_id,kennziffer,name LIMIT 1"); + $sql = "SELECT Strasse.* FROM Strasse + LEFT JOIN Hausnummer ON (Hausnummer.strasse_id = Strasse.id) + LEFT JOIN Plz ON (Plz.id = Hausnummer.plz_id) + LEFT JOIN Gemeinde ON (Gemeinde.id = Strasse.gemeinde_id) + LEFT JOIN GemeindeNetzgebiet ON (GemeindeNetzgebiet.gemeinde_id = Strasse.gemeinde_id) + LEFT JOIN Netzgebiet ON (GemeindeNetzgebiet.netzgebiet_id = Netzgebiet.id) + WHERE $where + GROUP BY Strasse.id + ORDER BY gemeinde_id,name,kennziffer + LIMIT 1"; + $res = $db->query($sql); if($db->num_rows($res)) { $data = $db->fetch_object($res); $item = new ADBStrasse($data); @@ -170,7 +180,7 @@ class ADBStrasseModel { if(array_key_exists("name%", $filter)) { $name = FronkDB::singleton()->escape($filter['name%']); if($name) { - $where .= " AND Strasse.`name` like '%$name%'"; + $where .= " AND Strasse.`name` like '$name%'"; } } @@ -184,7 +194,7 @@ class ADBStrasseModel { if(array_key_exists("gemeinde%", $filter)) { $gemeinde = FronkDB::singleton()->escape($filter['gemeinde%']); if($gemeinde) { - $where .= " AND Gemeinde.`name` like '%$gemeinde%'"; + $where .= " AND Gemeinde.`name` like '$gemeinde%'"; } } @@ -198,7 +208,7 @@ class ADBStrasseModel { if(array_key_exists("plz%", $filter)) { $plz = FronkDB::singleton()->escape($filter['plz%']); if($plz) { - $where .= " AND Plz.`plzstring` like '%$plz%'"; + $where .= " AND Plz.`plzstring` like '$plz%'"; } } diff --git a/application/ADBWohneinheit/ADBWohneinheit.php b/application/ADBWohneinheit/ADBWohneinheit.php index 61eea460c..24511f435 100644 --- a/application/ADBWohneinheit/ADBWohneinheit.php +++ b/application/ADBWohneinheit/ADBWohneinheit.php @@ -8,6 +8,20 @@ class ADBWohneinheit extends mfBaseModel { $this->table = "Wohneinheit"; } + protected function afterSave() { + if(!$this->id) return true; + if(!$this->hausnummer_id) return true; + + if(!defined("ADBWohneinheit_onSave_noAutoUnitCount") || !ADBWohneinheit_onSave_noAutoUnitCount) { + $unit_count = ADBWohneinheitModel::count(['hausnummer_id' => $this->hausnummer_id]); + $hausnummer = $this->getProperty("hausnummer"); + if($hausnummer->id) { + $hausnummer->unit_count = $unit_count; + $hausnummer->save(); + } + } + } + public static function parseHausnummerZusatz($text) { $data = []; @@ -53,6 +67,49 @@ class ADBWohneinheit extends mfBaseModel { return $data; } + public function getNewOAID() { + if(!$this->hausnummer_id) { + return false; + } + + $bcode = $this->getProperty("hausnummer")->oaid; + //var_dump($bcode); + if(!$bcode) { + return false; + } + + $codes = []; + + // get existing codes + $res = $this->db->select("Wohneinheit", "oaid", "oaid like '$bcode.%'"); + if($this->db->num_rows($res)) { + while($data = $this->db->fetch_object($res)) { + $codes[] = $data->oaid; + } + } else { + return $bcode.".001"; + } + + if(count($codes)) { + sort($codes); + } + + $last_code = end($codes); + + $m = []; + if(preg_match('/\.(\d+)$/', $last_code, $m)) { + if($m[1]) { + $last_num = $m[1]; + } + } else { + return false; + } + + $new_num = ++$last_num; + $code = $bcode.".".sprintf("%03d", $new_num); + return $code; + } + public function afterLoad() { //$this->hausnummer = new ADBHausnummer($this->hausnummer_id); //$this->loadStatus(); diff --git a/application/ADBWohneinheit/ADBWohneinheitModel.php b/application/ADBWohneinheit/ADBWohneinheitModel.php index 38ba34615..612b251ea 100644 --- a/application/ADBWohneinheit/ADBWohneinheitModel.php +++ b/application/ADBWohneinheit/ADBWohneinheitModel.php @@ -9,6 +9,7 @@ class ADBWohneinheitModel { public $stock; public $tuer; public $zusatz; + public $bezeichner; public $nutzung; public $create_by = null; @@ -46,7 +47,14 @@ class ADBWohneinheitModel { $db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME); $where = self::getSqlFilter($filter); - $res = $db->select("Wohneinheit", "*", "$where ORDER BY hausnummer_id,block,stiege,LENGTH(stock),stock,LENGTH(tuer),tuer LIMIT 1"); + $sql = "SELECT Wohneinheit.* FROM Wohneinheit + LEFT JOIN Hausnummer ON (Hausnummer.id = Wohneinheit.hausnummer_id) + WHERE $where + GROUP BY Wohneinheit.id + ORDER BY hausnummer_id,block,stiege,LENGTH(stock),stock,LENGTH(tuer),tuer,num + LIMIT 1"; + + $res = $db->query($sql); if($db->num_rows($res)) { $data = $db->fetch_object($res); $item = new ADBWohneinheit($data); @@ -64,7 +72,7 @@ class ADBWohneinheitModel { $db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME); - $res = $db->select("Wohneinheit", "*", "1=1 ORDER BY hausnummer_id,block,stiege,LENGTH(stock),stock,LENGTH(tuer),tuer"); + $res = $db->select("Wohneinheit", "*", "1=1 ORDER BY hausnummer_id,block,stiege,LENGTH(stock),stock,LENGTH(tuer),tuer,num"); if($db->num_rows($res)) { while($data = $db->fetch_object($res)) { $items[] = new ADBWohneinheit($data); @@ -87,7 +95,7 @@ class ADBWohneinheitModel { ) as tbl "; - mfLoghandler::singleton()->debug($sql); + //mfLoghandler::singleton()->debug($sql); $res = $db->query($sql); if($db->num_rows($res)) { $data = $db->fetch_object($res); @@ -105,9 +113,9 @@ class ADBWohneinheitModel { LEFT JOIN Hausnummer ON (Hausnummer.id = Wohneinheit.hausnummer_id) WHERE $where GROUP BY Wohneinheit.id - ORDER BY hausnummer_id,block,stiege,LENGTH(stock),stock,LENGTH(tuer),tuer"; + ORDER BY hausnummer_id,block,stiege,LENGTH(stock),stock,LENGTH(tuer),tuer,num"; - mfLoghandler::singleton()->debug($sql); + //mfLoghandler::singleton()->debug($sql); if(is_array($limit) && count($limit)) { if(is_numeric($limit['start']) && is_numeric($limit['count'])) { $sql .= " LIMIT ".$limit['start'].", ".$limit['count']; diff --git a/application/Address/Address.php b/application/Address/Address.php index 29340a0a7..889de6ae3 100644 --- a/application/Address/Address.php +++ b/application/Address/Address.php @@ -4,11 +4,12 @@ class Address extends mfBaseModel { protected $forcestr = ['street','company','zip','phone','fax','mobile','note']; private $parent; private $childaddresses; - private $links; - private $linked_as; + private $links = []; + private $linked_as = []; private $types; private $attributes; private $permissions; + private $contracts; private $phoneparts; @@ -181,6 +182,14 @@ class Address extends mfBaseModel { $this->childaddresses = AddressModel::search(['parent' => $this->id]); return $this->childaddresses; } + + if($name == "contracts") { + $owning = ContractModel::search(['owner_id' => $this->id]); + $billing = ContractModel::search(['billingaddress_id' => $this->id]); + $this->contracts = array_merge($owning, $billing); + return $this->contracts; + } + /* if($name == "links_to") { $links = AddressLinkModel::search(['address_id' => $this->id]); diff --git a/application/AddressDB/AddressDB.php b/application/AddressDB/AddressDB.php index c8b46818a..d30f6eeea 100644 --- a/application/AddressDB/AddressDB.php +++ b/application/AddressDB/AddressDB.php @@ -3,6 +3,46 @@ class AddressDB { private $db; private $log; + public static $wohneinheit_query = "select `Netzgebiet`.`id` AS `netzgebiet_id`, + `Netzgebiet`.`name` AS `netzgebiet`, + `Netzgebiet`.`extref` AS `netzgebiet_extref`, + `Gemeinde`.`id` AS `gemeinde_id`, + `Gemeinde`.`kennziffer` AS `gemeinde_kennziffer`, + `Gemeinde`.`code` AS `gemeinde_code`, + `Gemeinde`.`name` AS `gemeinde`, + `Ortschaft`.`id` AS `ortschaft_id`, + `Ortschaft`.`kennziffer` AS `ortschaft_kennziffer`, + `Ortschaft`.`name` AS `ortschaft`, + `Plz`.`plz` AS `plz`, + `Strasse`.`id` AS `strasse_id`, + `Strasse`.`kennziffer` AS `strasse_kennziffer`, + `Strasse`.`name` AS `strasse`, + `Hausnummer`.`id` AS `hausnummer_id`, + `Hausnummer`.`oaid` AS `hausnummer_oaid`, + `Hausnummer`.`hausnummer` AS `hausnummer`, + `Hausnummer`.`extref` AS `hausnummer_extref`, + `Hausnummer`.`grund_nr` AS `grund_nr`, + `Hausnummer`.`gps_lat` AS `gps_lat`, + `Hausnummer`.`gps_long` AS `gps_long`, + `Hausnummer`.`rollout` AS `rollout`, + `Hausnummer`.`rollout_info` AS `rollout_info`, + `Hausnummer`.`freigabe` AS `freigabe`, + `Wohneinheit`.`id` AS `wohneinheit_id`, + `Wohneinheit`.`oaid` AS `wohneinheit_oaid`, + `Wohneinheit`.`extref` AS `wohneinheit_extref`, + `Wohneinheit`.`num` AS `num`, + `Wohneinheit`.`block` AS `block`, + `Wohneinheit`.`stiege` AS `stiege`, + `Wohneinheit`.`stock` AS `stock`, + `Wohneinheit`.`tuer` AS `tuer`, + `Wohneinheit`.`bezeichner` AS `bezeichner`, + `Wohneinheit`.`zusatz` AS `zusatz` from `Hausnummer` + left join `Netzgebiet` on (`Hausnummer`.`netzgebiet_id` = `Netzgebiet`.`id`) + left join `Plz` on (`Plz`.`id` = `Hausnummer`.`plz_id`) + left join `Strasse` on (`Strasse`.`id` = `Hausnummer`.`strasse_id`) + left join `Ortschaft` on (`Ortschaft`.`id` = `Hausnummer`.`ortschaft_id`) + left join `Gemeinde` on (`Gemeinde`.`id` = `Strasse`.`gemeinde_id`) + left join `Wohneinheit` on (`Wohneinheit`.`hausnummer_id` = `Hausnummer`.`id`)"; public function __construct() { $this->db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME); @@ -30,4 +70,182 @@ class AddressDB { } } + /* + * methods to create or update an Address from strings + */ + + public function createUpdateHausnummer($data) { + $netzgebiet = null; + $gemeinde = null; + $ortschaft = null; + $strasse = null; + $plz = null; + $hausnummer = null; + + //var_dump($data);exit; + + if(!array_key_exists("netzgebiet_id", $data)) { + return false; + } + + foreach(["gemeinde", "ortschaft", "strasse", "plz"] as $field) { + $classname = "ADB".ucfirst($field); + $idfield = $field."_id"; + if(!array_key_exists($field."_id", $data)) continue; + $$field = new $classname($data[$idfield]); + if(!${$field}->id) { + $$field = null; + } + } + + + $netzgebiet = new ADBNetzgebiet($data['netzgebiet_id']); + if(!$netzgebiet->id) { + $this->log->debug(__CLASS__."::".__METHOD__.": Missing netzgebiet_id"); + return false; + } + + if(!$gemeinde) { + // dont allow creating Gemeinden + $this->log->debug(__CLASS__."::".__METHOD__.": Missing Gemeinde"); + return false; + } + + if(!$ortschaft) { + // search by kennziffer + if(array_key_exists("ortschaft_kennziffer", $data) && $data['ortschaft_kennziffer']) { + $ortschaft = ADBOrtschaftModel::getFirst(['kennziffer' => $data['ortschaft_kennziffer']]); + } + + if(!$ortschaft) { + // search by name + if(!array_key_exists("ortschaft", $data) || !$data['ortschaft']) return false; + $ortschaft = ADBOrtschaftModel::getFirst(['gemeinde_id' => $gemeinde->id, 'name' => $data['ortschaft']]); + } + + if(!$ortschaft) { + // create Ortschaft + $ortschaft = ADBOrtschaftModel::create([ + 'gemeinde_id' => $gemeinde->id, + 'kennziffer' => ($data['ortschaft_kennziffer']) ? $data['ortschaft_kennziffer'] : null, + 'name' => $data['ortschaft'] + ]); + if(!$ortschaft->save()) { + $this->log->debug(__CLASS__."::".__METHOD__.": Cannot save Ortschaft"); + return false; + } + } + } + + if(!$strasse) { + // search by kennziffer + if(array_key_exists("strasse_kennziffer", $data) && $data['strasse_kennziffer']) { + $strasse = ADBStrasseModel::getFirst(['kennziffer' => $data['strasse_kennziffer']]); + } + + if(!$strasse) { + // search by name + if(!array_key_exists("strasse", $data) || !$data['strasse']) return false; + $strasse = ADBStrasseModel::getFirst(['gemeinde_id' => $gemeinde->id, 'name' => $data['strasse']]); + } + + if(!$strasse) { + // create Strasse + if(!array_key_exists("strasse", $data) || !$data['strasse']) return false; + $strasse = ADBStrasseModel::create([ + 'gemeinde_id' => $gemeinde->id, + 'kennziffer' => ($data['strasse_kennziffer']) ? $data['strasse_kennziffer'] : null, + 'name' => $data['strasse'] + ]); + if(!$strasse->save()) { + $this->log->debug(__CLASS__."::".__METHOD__.": Cannot save Strasse"); + return false; + } + } + } + + if(!$plz) { + // search by plz + if(!array_key_exists("plz", $data) || !$data['plz']) return false; + $plz = ADBPlzModel::getFirst(['gemeinde_id' => $gemeinde->id, 'plz' => $data['plz']]); + if(!$plz) { + // create PLZ + $plz = ADBPlzModel::create([ + 'gemeinde_id' => $gemeinde->id, + 'plz' => $data['plz'], + 'plzstring' => $data['plz'] + ]); + if(!$plz->save()) { + $this->log->debug(__CLASS__."::".__METHOD__.": Cannot save PLZ"); + return false; + } + } + } + + if(array_key_exists("hausnummer_id", $data)) { + // if hausnummer_id is set but empty => fail + if(!$data['hausnummer_id']) return false; + $hausnummer = new ADBHausnummer($data['hausnummer_id']); + if(!$hausnummer->id) { + return false; + } + } + + $me = new User(); + $me->loadMe(); + + // build hausnummer data + //$hausnummer_data['oaid'] = (array_key_exists("oaid", $data) && $data['oaid']) ? $data['oaid'] : null; + $hausnummer_data['adrcd'] = ($data['adrcd']) ? $data['adrcd'] : null; + $hausnummer_data['extref'] = ($data['extref']) ? $data['extref'] : null; + $hausnummer_data['netzgebiet_id'] = $netzgebiet->id; + $hausnummer_data['ortschaft_id'] = $ortschaft->id; + $hausnummer_data['plz_id'] = $plz->id; + $hausnummer_data['strasse_id'] = $strasse->id; + $hausnummer_data['hausnummer'] = $data['hausnummer']; + $hausnummer_data['grund_nr'] = $data['grund_nr']; + $hausnummer_data['gps_lat'] = ($data['gps_lat']) ? str_replace(",", ".", $data['gps_lat']) : null; + $hausnummer_data['gps_long'] = ($data['gps_long']) ? str_replace(",", ".", $data['gps_long']) : null; + $hausnummer_data['rollout'] = (trim($data['rollout'])) ? trim($data['rollout']) : null; + $hausnummer_data['rollout_info'] = (trim($data['rollout_info'])) ? trim($data['rollout_info']) : null; + $hausnummer_data['freigabe'] = json_encode($data['freigabe']); + $hausnummer_data['manual_add'] = date('U'); + $hausnummer_data['manual_add_by'] = $me->id; + $hausnummer_data['manual_add_info'] = "thetool user ".$me->username." via AddressDB"; + $hausnummer_data['manual_update'] = date('U'); + $hausnummer_data['manual_update_by'] = $me->id; + $hausnummer_data['manual_update_info'] = "thetool user ".$me->username." via AddressDB"; + + //var_dump($hausnummer_data, $hausnummer);exit; + + if(!$hausnummer) { + // create hausnummer + $hausnummer = ADBHausnummerModel::create($hausnummer_data); + } else { + // update hausnummer + $hausnummer->update($hausnummer_data); + } + + $hausnummer_id = $hausnummer->save(); + if(!$hausnummer_id) { + $this->log->debug(__CLASS__."::".__METHOD__.": Cannot save Hausnummer"); + return false; + } + + // create OAID + if(!$hausnummer->oaid) { + $hausnummer->oaid = $hausnummer->getNewOAID(); + if(!$hausnummer->save()) { + $this->log->debug(__CLASS__."::".__METHOD__.": Cannot save Hausnummer OAID"); + } + } + + + return $hausnummer_id; + } + + public function updateHausnummer($hausnummer_id, $data) { + + } + } \ No newline at end of file diff --git a/application/AddressDB/AddressDBController.php b/application/AddressDB/AddressDBController.php index 051f054f5..9fb85ea69 100644 --- a/application/AddressDB/AddressDBController.php +++ b/application/AddressDB/AddressDBController.php @@ -9,11 +9,374 @@ class AddressDBController extends mfBaseController { $this->me = $me; $this->layout()->set("me",$me); - if(!$me->is(["Admin", "netowner", "pipeplanner"])) { + if(!$me->is(["Admin", "netowner"])) { $this->redirect("Dashboard"); } } + + protected function indexAction() { + $this->layout()->setTemplate("AddressDB/Index"); + + $rfilter = $this->request->filter; + iF(!is_array($rfilter)) { + $rfilter = []; + } + + $this->layout->set("filter", $rfilter); + + $filter = $this->getPreparedFilter($rfilter); + + // pagination defaults + $pagination = []; + $pagination['start'] = 0; + $pagination['count'] = 25; + $pagination['maxItems'] = 0; + + if(is_numeric($this->request->s)) { + $pagination['start'] = intval($this->request->s); + } + + + if($this->me->is("Admin")) { + $my_networks = NetworkModel::getAll(); + if($filter['network_id']) { + $filter['netzgebiet_id'] = $filter['network_id']; + } + } else { + $my_networks = $this->me->myNetworks(["netowner", "salespartner"]); + } + + $netzgebiet_ids = []; + $my_adb_networks = []; + foreach($my_networks as $network) { + if($network->adb_netzgebiet_id && !in_array($network->adb_netzgebiet_id, $netzgebiet_ids)) { + $netzgebiet_ids[] = $network->adb_netzgebiet_id; + $my_adb_networks[$network->adb_netzgebiet_id] = new ADBNetzgebiet($network->adb_netzgebiet_id); + } + } + //var_dump($my_networks, $my_adb_networks); + if(!$this->me->is("Admin") && array_key_exists("network_id", $filter)) { + if(array_key_exists($filter['network_id'], $my_adb_networks)) { + $filter['netzgebiet_id'] = $filter['network_id']; + } else { + unset($filter['network_id']); + } + + } + + $addressdb_filter = $filter; + if(!array_key_exists("netzgebiet_id", $addressdb_filter)) { + $addressdb_filter['netzgebiet_id'] = $netzgebiet_ids; + } + //var_dump($my_adb_networks);exit; + $this->layout()->set("my_networks", ADBNetzgebietModel::getAll()); + $this->layout()->set("my_adb_networks", $my_adb_networks); + //var_dump($addressdb_filter);exit; + + if($filter['netzgebiet_id'] === "null") { + $addressdb_filter['netzgebiet_id'] = 0; + $pagination['maxItems'] = ADBHausnummerModel::count($addressdb_filter); + $addresses = ADBHausnummerModel::search($addressdb_filter, $pagination); + } else if(count($my_adb_networks)) { + $pagination['maxItems'] = ADBHausnummerModel::count($addressdb_filter); + $addresses = ADBHausnummerModel::search($addressdb_filter, $pagination); + } + $this->layout()->set("pagination", $pagination); + $this->layout()->set("addresses", $addresses); + + // get filter lists + $filter_filter = []; + if(array_key_exists("netzgebiet_id", $addressdb_filter)) { + $filter_filter["netzgebiet_id"] = $netzgebiet_ids; + $this->layout()->set("gemeinden", ADBGemeindeModel::search($filter_filter)); + if(array_key_exists("gemeinde_id", $addressdb_filter)) { + $filter_filter['gemeinde_id'] = $addressdb_filter['gemeinde_id']; + } + $this->layout()->set("ortschaften", ADBOrtschaftModel::search($filter_filter)); + } + + + } + + protected function getPreparedFilter($filter) { + $new_filter = []; + + if(array_key_exists("street", $filter) && $filter['street']) { + $new_filter['strasse%'] = "%".$filter['street']; + unset($filter['street']); + } + + if(array_key_exists("adrcd", $filter) && $filter['adrcd']) { + $new_filter['adrcd%'] = $filter['adrcd']; + unset($filter['adrcd']); + } + + if(array_key_exists("oaid", $filter) && $filter['oaid']) { + $new_filter['oaid%'] = $filter['oaid']; + unset($filter['oaid']); + } + + if(array_key_exists("extref", $filter) && $filter['extref']) { + $new_filter['extref%'] = "%".$filter['extref']; + unset($filter['extref']); + } + + if(array_key_exists("zip", $filter) && $filter['zip']) { + $new_filter['plz%'] = $filter['zip']; + unset($filter['zip']); + } + + if(array_key_exists("rollout", $filter) && $filter['rollout']) { + $new_filter['rollout%'] = $filter['rollout']; + unset($filter['rollout']); + } + + if(array_key_exists("rollout_info", $filter) && $filter['rollout_info']) { + $new_filter['rollout_info%'] = $filter['rollout_info']; + unset($filter['rollout_info']); + } + + if(array_key_exists("gemeinde", $filter) && $filter['gemeinde']) { + $new_filter['gemeinde%'] = $filter['gemeinde']; + unset($filter['gemeinde']); + unset($filter['gemeinde_id']); + } + + if(array_key_exists("ortschaft", $filter) && $filter['ortschaft']) { + $new_filter['ortschaft%'] = $filter['ortschaft']; + unset($filter['ortschaft']); + unset($filter['ortschaft_id']); + } + + if(is_array($filter) && count($filter)) { + foreach($filter as $name => $value) { + if(strlen($value) > 0) $new_filter[$name] = $value; + } + } + + return $new_filter; + } + + protected function addAction() { + $this->layout()->setTemplate("AddressDB/Form"); + + if($this->me->is("Admin")) { + $my_networks = NetworkModel::getAll(); + } else { + $my_networks = $this->me->myNetworks(["netowner", "salespartner"]); + } + + $netzgebiet_ids = []; + $my_adb_networks = []; + foreach($my_networks as $network) { + if($network->adb_netzgebiet_id && !in_array($network->adb_netzgebiet_id, $netzgebiet_ids)) { + $netzgebiet_ids[] = $network->adb_netzgebiet_id; + $my_adb_networks[$network->adb_netzgebiet_id] = new ADBNetzgebiet($network->adb_netzgebiet_id); + } + } + $this->layout()->set("my_adb_networks", $my_adb_networks); + + + $save_data = []; + foreach($this->request->get() as $key => $value) { + $save_data[$key] = $value; + } + //var_dump($save_data);exit; + $this->layout()->set("save_data", $save_data); + + } + + protected function editAction() { + + $id = $this->request->id; + if(!is_numeric($id) || $id < 1) { + $this->layout()->setFlash("Adresse nicht gefunden", "error"); + $this->redirect("AddressDB"); + } + + $hausnummer = new ADBHausnummer($id); + if(!$hausnummer->id) { + $this->layout()->setFlash("Adresse nicht gefunden", "error"); + $this->redirect("AddressDB"); + } + + /*if(!in_array($hausnummer->netzgebiet_id, $my_adb_networks)) { + $this->layout()->setFlash("Adresse nicht gefunden", "error"); + $this->redirect("AddressDB"); + }*/ + + $this->layout()->set("address", $hausnummer); + + return $this->addAction(); + } + + protected function saveAction() { + $r = $this->request; + $id = $r->id; + //var_dump($r->get());exit; + + $address_data = []; + + if(is_numeric($id) && $id > 0) { + $mode = "edit"; + $hausnummer = new ADBHausnummer($id); + if(!$hausnummer->id) { + $this->layout()->setFlash("Addresse nicht gefunden", "error"); + $this->redirect("AddressDB"); + } + $address_data['hausnummer_id'] = $hausnummer->id; + } else { + $mode = "add"; + } + + $required = ['netzgebiet_id','strasse','hausnummer','plz','ortschaft','gemeinde']; + foreach(['adrcd','extref','netzgebiet_id','strasse','hausnummer','plz','ortschaft','gemeinde','grund_nr','gps_lat','gps_long','unit_count'] as $field) { + if(in_array($field, $required)) { + if(!trim($r->$field)) { + $this->layout()->setFlash("'".ucfirst($field)."' darf nicht leer sein!", "error"); + return $this->addAction(); + //$this->redirect("AddressDB", $mode, ['id' => $id]); + } + } + $address_data[$field] = $this->db()->escape(trim($r->$field)); + } + + $gemeinde = ADBGemeindeModel::getFirst(['name' => $address_data['gemeinde']]); + if(!$gemeinde->id) { + $this->layout()->setFlash("Gemeinde nicht gefunden", "error"); + return $this->addAction(); + //$this->redirect("AddressDB", $mode, ['id' => $id]); + } + + $address_data['gemeinde_id'] = $gemeinde->id; + + $freigabe = []; + if(is_array($r->freigabe) && count($r->freigabe)) { + if(in_array("interest", $r->freigabe)) { + $freigabe[] = "interest"; + } + if(in_array("provision", $r->freigabe)) { + $freigabe[] = "provision"; + } + if(in_array("order", $r->freigabe)) { + $freigabe[] = "order"; + } + if(in_array("reorder", $r->freigabe)) { + $freigabe[] = "reorder"; + } + + } + + $address_data['freigabe'] = $freigabe; + + $rollout = null; + $rollout_info = null; + if(trim($r->rollout)) { + $rollout = intval(trim($r->rollout)); + } + if(trim($r->rollout_info)) { + $rollout_info = trim($r->rollout_info); + } + if(!$rollout_info) { + $rollout_info = "unscheduled"; + } + + $address_data['rollout'] = $rollout; + $address_data['rollout_info'] = $rollout_info; + + //var_dump($address_data);exit; + + $adb = new AddressDB(); + $hausnummer_id = $adb->createUpdateHausnummer($address_data); + if(!$hausnummer_id) { + $this->layout()->setFlash("Fehler beim Erstellen der Adresse!", "error"); + return $this->addAction(); + //$this->redirect("AddressDB"); + } + + if($mode == "add") { + $hausnummer = new ADBHausnummer($hausnummer_id); + + /* + * Wohneinheiten erstellen + */ + if($r->unit_count > 0) { + for($i = 1; $i <= $r->unit_count; $i++) { + $unit = ADBWohneinheitModel::create([ + 'hausnummer_id' => $hausnummer_id, + 'num' => $i, + ]); + $unit_id = $unit->save(); + if(!$unit_id) { + $this->log->debug(__CLASS__."::".__METHOD__.": Cannot save Woneinheit"); + continue; + } + $unit->oaid = $unit->getNewOAID(); + $unit->save(); + } + } + } + + $qs = http_build_query(['filter' => ['oaid' => $hausnummer->oaid]]); + //var_dump($qs);exit; + $this->layout()->setFlash("Adresse erfolgreich gespeichert", "success"); + $this->redirect("AddressDB", "Index", $qs); + + } + + protected function exportAction() { + $rfilter = $this->request->filter; + if(!is_array($rfilter)) { + $rfilter = []; + } + $filter = $this->getPreparedFilter($rfilter); + + + if($this->me->is("Admin")) { + $my_networks = NetworkModel::getAll(); + } else { + $my_networks = $this->me->myNetworks(["netowner", "salespartner"]); + } + + $netzgebiet_ids = []; + $my_adb_networks = []; + foreach($my_networks as $network) { + if($network->adb_netzgebiet_id && !in_array($network->adb_netzgebiet_id, $netzgebiet_ids)) { + $netzgebiet_ids[] = $network->adb_netzgebiet_id; + $my_adb_networks[$network->adb_netzgebiet_id] = new ADBNetzgebiet($network->adb_netzgebiet_id); + } + } + + if(array_key_exists("network_id", $filter) && $filter['network_id']) { + if($this->me->is("Admin")) { + $filter['netzgebiet_id'] = $filter['network_id']; + } else { + if(in_array($filter['network_id'], $netzgebiet_ids)) { + $filter['netzgebiet_id'] = $filter['network_id']; + } + } + } + unset($filter['network_id']); + + $addressdb_filter = $filter; + if(!array_key_exists("netzgebiet_id", $addressdb_filter)) { + $addressdb_filter['netzgebiet_id'] = $netzgebiet_ids; + } + + // Get mysqli resource from Model so layout can output data as it's retrieved + // Fixes lousy performance and horrendous memory usage + $res = ADBHausnummerModel::search($addressdb_filter, [], true); + + $this->layout()->setTemplate("AddressDB/export.csv"); + $this->layout()->set("res", $res); + + //var_dump($filter, $hausnummern);exit; + + + + } + protected function apiAction() { if(!$this->me->is(["Admin","netowner"])) { $this->redirect("Dashboard"); @@ -28,12 +391,24 @@ class AddressDBController extends mfBaseController { case "getFilteredBuildings": $return = $this->getFilteredBuildingsApi(); break; + case "getAddressByHousenumber": + $return = $this->getAddressByHousenumberApi(); + break; case "getUnits": $return = $this->getUnitsApi(); break; + case "findStreets": + $return = $this->findStreetsApi(); + break; + case "findDistricts": + $return = $this->findDistrictsApi(); + break; case "findCities": $return = $this->findCitiesApi(); break; + case "findZips": + $return = $this->findZipsApi(); + break; case 'findBuildings': $return = $this->findBuildingsApi(); break; @@ -55,6 +430,20 @@ class AddressDBController extends mfBaseController { private function findAddressApi() { $addresses = []; $search = trim($this->request->q); + $campagin_id = ($this->request->campaign_id); + + $campaign = new Preordercampaign($campagin_id); + if(!$campaign->id) { + header("Content-Type: application/json"); + echo json_encode(["results" => []]); + exit; + } + + $scluster_ids = []; + foreach($campaign->salesclusters as $scluster) { + $scluster_ids[] = $scluster->id; + } + $results = []; $search_parts = explode(" ", $search); @@ -62,19 +451,25 @@ class AddressDBController extends mfBaseController { $ort_search = $strasse_search = $plz_search = $hausnummer_search = []; foreach($search_parts as $p) { - $p = trim($p); + $p = $this->db->escape(trim($p)); if(!$p) continue; - $ort_search[] = "ortschaft like '%$p%'"; - $strasse_search[] = "strasse like '%$p%'"; + $ort_search[] = "ortschaft like '$p%'"; + $strasse_search[] = "strasse like '$p%'"; $plz_search[] = "plz like '%$p%'"; $hausnummer_search[] = "hausnummer like '%$p%'"; } - $sql = "SELECT * FROM view_hausnummer WHERE (".implode(" OR ", $ort_search).") OR (".implode(" OR ", $strasse_search).") OR (".implode(" OR ", $plz_search).") OR (".implode(" OR ", $hausnummer_search).")"; - //echo $sql;exit; + $where = "1=1"; + if(count($scluster_ids)) { + $where .= " AND netzgebiet_id IN (".implode(', ',$scluster_ids).")"; + } + + $sql = "SELECT * FROM view_hausnummer WHERE $where AND ((".implode(" OR ", $ort_search).") OR (".implode(" OR ", $strasse_search).") OR (".implode(" OR ", $plz_search).") OR (".implode(" OR ", $hausnummer_search).")) ORDER BY strasse, LENGTH(hausnummer), hausnummer"; + $this->log->debug($sql); $adb = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME); $res = $adb->query($sql); + $this->log->debug("done"); if(!$adb->num_rows($res)) { header("Content-Type: application/json"); @@ -84,22 +479,39 @@ class AddressDBController extends mfBaseController { while($data = $adb->fetch_object($res)) { $address_string = $data->plz." ".$data->ortschaft.", ".$data->strasse." ".$data->hausnummer; + $sort_key = $data->plz." ".$data->ortschaft." ".$data->strasse; $address = []; $address['id'] = $data->hausnummer_id; $address["text"] = $address_string; + $address['sort_key'] = $sort_key; $addresses[] = $address; } // sort results by most occurences of search strings $sort = []; - foreach($addresses as $address) { + foreach($addresses as $key => $address) { + $includes_int = false; $count = 0; foreach($search_parts as $p) { - $count += substr_count(strtolower($address['text']), strtolower($p)); + $p = $this->db->escape(trim($p)); + if(!$p) continue; + if(is_numeric(($p))) { + $includes_int = true; + if(substr_count(strtolower($address['text']), strtolower($p))) { + $count++; + } + } else { + $count += substr_count(strtolower($address['text']), strtolower($p)); + } } + unset($address['sort_key']); //echo $address['text']." $p $count
    \n"; + + if($includes_int && (($count + 1) - count($search_parts) ) < 1) { + continue; + } if(!array_key_exists($count, $sort)) { $sort[$count] = []; } @@ -136,7 +548,7 @@ class AddressDBController extends mfBaseController { $u = []; $u['id'] = $unit->id; $u['zip'] = $unit->hausnummer->plz->plzstring; - $u['city'] = $unit->hausnummer->strasse->ortschaft->name; + $u['city'] = $unit->hausnummer->ortschaft->name; $u['street'] = $unit->hausnummer->strasse->name; $u['housenumber'] = $unit->hausnummer->hausnummer; $u['block'] = $unit->block; @@ -152,15 +564,109 @@ class AddressDBController extends mfBaseController { return ['units' => $results]; } - private function findCitiesApi() { - $cities = []; - $search = $this->request->search; + private function getAddressByHousenumberApi() { + $zips = []; + $hausnummer_id = trim($this->request->hausnummer_id); - $ort_ids = []; + if(!is_numeric($hausnummer_id) || $hausnummer_id < 1) { + return false; + } + $hausnummer = new ADBHausnummer($hausnummer_id); + + $result = [ + 'hausnummer_id' => $hausnummer->id, + 'strasse' => $hausnummer->strasse->name, + 'hausnummer' => $hausnummer->hausnummer, + 'plz' => $hausnummer->plz->plz, + 'ort' => $hausnummer->strasse->gemeinde->name, + 'ortschaft' => $hausnummer->ortschaft->name + ]; + + return $result; + } + + private function findStreetsApi() { + $streets = []; + $search = trim($this->request->q); + + foreach(ADBStrasseModel::search(['name%' => $search]) as $street) { + if(!in_array($street->name, $streets)) { + $streets[] = $street->name; + } + } + + $this->returnJson($streets); + } + + private function findZipsApi() { + $zips = []; + $search = trim($this->request->q); + $campaign_id = trim($this->request->campaign_id); + + $plz_search = []; + + if($campaign_id) { + $campaign = new Preordercampaign($campaign_id); + if(!$campaign->id) { + header("Content-Type: application/json"); + echo json_encode(["results" => []]); + exit; + } + + $scluster_ids = []; + foreach($campaign->salesclusters as $scluster) { + $scluster_ids[] = $scluster->id; + } + $plz_search['netzgebiet_id'] = $scluster_ids; + } + + $plz_search['plzstring%'] = $search; + + + foreach(ADBPlzModel::search($plz_search) as $zip) { + if(!in_array($zip->plz, $zips)) { + $zips[] = $zip->plz; + } + } + + $this->returnJson($zips); + } + + private function findDistrictsApi() { + $districts = []; + $search = trim($this->request->q); + $autocomplete = $this->request->autocomplete; + $campaign_id = trim($this->request->campaign_id); + + $district_search = []; + + if($campaign_id) { + $campaign = new Preordercampaign($campaign_id); + if(!$campaign->id) { + header("Content-Type: application/json"); + echo json_encode(["results" => []]); + exit; + } + + $scluster_ids = []; + foreach($campaign->salesclusters as $scluster) { + $scluster_ids[] = $scluster->id; + } + $district_search['netzgebiet_id'] = $scluster_ids; + } + + $district_search['name%'] = "%".$search; + + foreach(ADBOrtschaftModel::search($district_search) as $district) { + if(!in_array($district->name, $districts)) { + $districts[] = $district->name; + } + } + /* if(is_numeric($search)) { $adb = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME); - $sql = "SELECT ortschaft_id from view_wohneinheit WHERE plz like '%$search%' GROUP BY ortschaft_id"; + $sql = "SELECT ortschaft_id from view_wohneinheit WHERE ortschaft like '%$search%' GROUP BY ortschaft_id"; $res = $adb->query($sql); if($adb->num_rows($res)) { @@ -178,9 +684,18 @@ class AddressDBController extends mfBaseController { $results = ADBOrtschaftModel::search(['name%' => $search]); } + if($autocomplete) { + foreach($results as $city) { + if(!in_array($city->name, $cities)) { + $cities[] = $city->name; + } + } + $this->returnJson($cities); + } + foreach($results as $city) { $gemeinde = new ADBGemeinde($city->gemeinde_id); - + $data = []; $data['id'] = $city->id; $data['gemeinde_id'] = $city->gemeinde_id; @@ -189,8 +704,43 @@ class AddressDBController extends mfBaseController { $data['name'] = $city->name; $cities[] = $data; } + */ + $this->returnJson($districts); + //return ['cities' => $cities]; + } + + private function findCitiesApi() { + $cities = []; + $search = $this->request->q; + //$autocomplete = $this->request->autocomplete; + $campaign_id = trim($this->request->campaign_id); + + $city_search = []; + + if($campaign_id) { + $campaign = new Preordercampaign($campaign_id); + if(!$campaign->id) { + header("Content-Type: application/json"); + echo json_encode(["results" => []]); + exit; + } + + $scluster_ids = []; + foreach($campaign->salesclusters as $scluster) { + $scluster_ids[] = $scluster->id; + } + $city_search['netzgebiet_id'] = $scluster_ids; + } + + $city_search['name%'] = "%".$search; + + foreach(ADBGemeindeModel::search($city_search) as $city) { + if(!in_array($city->name, $cities)) { + $cities[] = $city->name; + } + } + $this->returnJson($cities); - return ['cities' => $cities]; } private function getFilteredBuildingsApi() { diff --git a/application/Addresstype/AddresstypeModel.php b/application/Addresstype/AddresstypeModel.php index 992228eec..0f30428ff 100644 --- a/application/Addresstype/AddresstypeModel.php +++ b/application/Addresstype/AddresstypeModel.php @@ -114,19 +114,21 @@ class AddresstypeModel { /* * Address Type */ - if(is_array($filter['addresstype']) && count($filter['addresstype'])) { - $at = $filter['addresstype']; - $in = []; - foreach(TT_ROLES as $role) { - if(in_array($role, $at)) { - $in[] = "Addresstype.type = '$role'"; + if(array_key_exists('addresstype', $filter)) { + if(is_array($filter['addresstype']) && count($filter['addresstype'])) { + $at = $filter['addresstype']; + $in = []; + foreach(TT_ROLES as $role) { + if(in_array($role, $at)) { + $in[] = "Addresstype.type = '$role'"; + } + } + + $or = ""; + if(count($in)) { + $or = implode(" OR ", $in); + $where .= " AND ( $or )"; } - } - - $or = ""; - if(count($in)) { - $or = implode(" OR ", $in); - $where .= " AND ( $or )"; } } diff --git a/application/Admin/AdminController.php b/application/Admin/AdminController.php new file mode 100644 index 000000000..b99bff025 --- /dev/null +++ b/application/Admin/AdminController.php @@ -0,0 +1,41 @@ +needlogin=true; + $me = new User(); + $me->loadMe(); + $this->me = $me; + $this->layout()->set("me",$me); + + if(!$me->is(["Admin"])) { + $this->redirect("Dashboard"); + } + } + + protected function indexAction() { + $this->layout()->setTemplate("Admin/Index"); + + } + + + protected function createNetworkAddressForNetowner() { + $i = 0; + foreach(NetworkModel::getAll() as $network) { + $netaddress = NetworkAddressModel::getFirst(["network_id" => $network->id, "address_id" => $network->owner_id, "addresstype" => "netowner"]); + if(!$netaddress) { + $netaddress = NetworkAddressModel::create([ + 'network_id' => $network->id, + 'address_id' => $network->owner_id, + 'type' => "netowner" + ]); + $netaddress->save(); + $i++; + } + } + $this->layout()->setFlash("$i NetworkAddress Objekte angelegt.", "success"); + $this->redirect("Admin"); + } + +} \ No newline at end of file diff --git a/application/Api/v1/AddressdbApicontroller.php b/application/Api/v1/AddressdbApicontroller.php index 528dafa32..8815d5a44 100644 --- a/application/Api/v1/AddressdbApicontroller.php +++ b/application/Api/v1/AddressdbApicontroller.php @@ -4,20 +4,26 @@ class AddressdbApicontroller extends mfBaseApicontroller { private $campaigns = []; private $filter_salescluster_ids = []; private $campaigns_by_scluster = []; - private $allowed_preordertypes = []; + private $district_is_city = false; + private $hausnummer_add_zusatz = false; protected function init() { $db = $this->db(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME); + $this->addRoute("/addressdb/getClusters", "getClusters", "GET"); $this->addRoute("/addressdb/findAddress", "find", "GET"); $this->addRoute("/addressdb/findAddress", "find", "POST"); - $this->addRoute("/addressdb/findStreet", "findStreet", "GET"); + $this->addRoute("/addressdb/searchAddress", "search", "GET"); + $this->addRoute("/addressdb/searchAddress", "search", "POST"); + $this->addRoute("/addressdb/findStreet", "findStreet", "GET"); $this->addRoute("/addressdb/findStreet", "findStreet", "POST"); $this->addRoute("/addressdb/findZip", "findZip", "GET"); $this->addRoute("/addressdb/findZip", "findZip", "POST"); $this->addRoute("/addressdb/findCity", "findCity", "GET"); $this->addRoute("/addressdb/findCity", "findCity", "POST"); + $this->addRoute("/addressdb/findDistrict", "findDistrict", "GET"); + $this->addRoute("/addressdb/findDistrict", "findDistrict", "POST"); $this->allowMissingOrigin = true; } @@ -33,10 +39,7 @@ class AddressdbApicontroller extends mfBaseApicontroller { $this->filter_salescluster_ids[] = $campain_scluster->salescluster_id; } - if(!array_key_exists($campain_scluster->salescluster_id, $this->campaigns_by_scluster)) { - $this->campaigns_by_scluster[$campain_scluster->salescluster_id] = []; - } - $this->campaigns_by_scluster[$campain_scluster->salescluster_id][] = $campaign->id; + $this->campaigns_by_scluster[$campain_scluster->salescluster_id] = $campaign->id; } $this->campaigns[$campaign->id] = $campaign; @@ -47,6 +50,14 @@ class AddressdbApicontroller extends mfBaseApicontroller { $this->allowed_preordertypes[] = $type->type; } } + + if($campaign->district_is_city == 1) { + $this->district_is_city = true; + } + + if($campaign->hausnummer_add_zusatz == 1) { + $this->hausnummer_add_zusatz = true; + } } foreach(PreordercampaignOriginhostnameModel::search(['preordercampaign_id' => $campaign->id]) as $origin) { @@ -61,6 +72,23 @@ class AddressdbApicontroller extends mfBaseApicontroller { } + protected function getClusters() { + $cluster_search = []; + if(count($this->filter_salescluster_ids)) { + $cluster_search['netzgebiet_id'] = $this->filter_salescluster_ids; + } + $clusters = []; + foreach(ADBNetzgebietModel::search($cluster_search) as $cluster) { + $c = []; + $c['id'] = $cluster->extref; + $c['name'] = $cluster->name; + $clusters[] = $c; + } + + return mfResponse::Ok(["clusters" => $clusters]); + + } + protected function findCity() { // unofficially supporting GET and POST in v1 $get = array_merge($this->post, $this->get); @@ -68,13 +96,15 @@ class AddressdbApicontroller extends mfBaseApicontroller { // search parameter is unofficially deprecated but still supported $search = trim($get['search']); $city = trim($get['city']); + $district = trim($get['district']); $zip = trim($get['zip']); + $search_cluster_id = trim($get['cluster_id']); if(!$city) { $city = $search; } - if(!$city && !$zip) { + if(!$city && !$zip && !$search_cluster_id) { return mfResponse::BadRequest(['message' => "No search parameters"]); } @@ -82,12 +112,23 @@ class AddressdbApicontroller extends mfBaseApicontroller { if($zip) { $city_search['plz%'] = $zip; } + if($district) { + $district_search['ortschaft%'] = $zip; + } if(count($this->filter_salescluster_ids)) { $city_search['netzgebiet_id'] = $this->filter_salescluster_ids; } - $results = ADBGemeindeModel::search($city_search); + if($search_cluster_id) { + $city_search['netzgebiet_extref'] = $search_cluster_id; + } + + if($this->district_is_city) { + $results = ADBOrtschaftModel::search($city_search); + } else { + $results = ADBGemeindeModel::search($city_search); + } $cities = []; @@ -99,6 +140,62 @@ class AddressdbApicontroller extends mfBaseApicontroller { return mfResponse::Ok(['cities' => array_values($cities)]); } + protected function findDistrict() { + // unofficially supporting GET and POST in v1 + $get = array_merge($this->post, $this->get); + + // search parameter is unofficially deprecated but still supported + $search = $this->db()->escape(trim($get['search'])); + $city = $this->db()->escape(trim($get['city'])); + $district = $this->db()->escape(trim($get['district'])); + $zip = $this->db()->escape(trim($get['zip'])); + $search_cluster_id = $this->db()->escape(trim($get['cluster_id'])); + + if(!$district) { + $district = $search; + } + /* + if(!$city && !$zip && !$district) { + return mfResponse::BadRequest(['message' => "No search parameters"]); + }*/ + + $where = "1=1"; + + if($district && $district != "%") { + $where .= " AND ortschaft like '$district%'"; + } + if($city && $city != "%") { + $where .= " AND gemeinde like '$city%'"; + } + if($zip && $zip != "%") { + $where .= " AND plz like '$zip%'"; + } + + if(count($this->filter_salescluster_ids)) { + $where .= " AND netzgebiet_id IN (".join(", ", $this->filter_salescluster_ids).")"; + } + + if($search_cluster_id) { + $where .= " AND netzgebiet_extref='$search_cluster_id'"; + } + + $cities = []; + + $sql = "SELECT gemeinde, ortschaft FROM view_hausnummer WHERE $where GROUP BY gemeinde,ortschaft_id ORDER BY gemeinde, ortschaft"; + //echo $sql;exit; + $res = $this->db()->query($sql); + if($this->db()->num_rows($res)) { + while($data = $this->db()->fetch_object($res)) { + if(!array_key_exists($data->gemeinde, $cities)) { + $cities[$data->gemeinde] = []; + } + $cities[$data->gemeinde][] = $data->ortschaft; + } + } + + return mfResponse::Ok(['cities' => $cities]); + } + protected function findZip() { // unofficially supporting GET and POST in v1 $get = array_merge($this->post, $this->get); @@ -106,8 +203,9 @@ class AddressdbApicontroller extends mfBaseApicontroller { // search parameter is unofficially deprecated but still supported $search = trim($get['search']); $zip = trim($get['zip']); + $search_cluster_id = trim($get['cluster_id']); - if(!$search && !$zip) { + if(!$search && !$zip && !$search_cluster_id) { return mfResponse::BadRequest(['message' => "Searchstring cannot be empty!"]); } @@ -116,11 +214,16 @@ class AddressdbApicontroller extends mfBaseApicontroller { } $zip_search = ['plzstring%' => $zip]; - + //var_dump($this->filter_salescluster_ids);exit; if(count($this->filter_salescluster_ids)) { $zip_search['netzgebiet_id'] = $this->filter_salescluster_ids; } + if($search_cluster_id) { + $zip_search['netzgebiet_extref'] = $search_cluster_id; + } + + //var_dump($zip_search);exit; $results = ADBPlzModel::search($zip_search); @@ -138,12 +241,13 @@ class AddressdbApicontroller extends mfBaseApicontroller { $get = array_merge($this->post, $this->get); // search parameter is unofficially deprecated but still supported - $search = trim($get['search']); - $street = trim($get['street']); - $city = trim($get['city']); - $zip = trim($get['zip']); + $search = $this->db()->escape(trim($get['search'])); + $street = $this->db()->escape(trim($get['street'])); + $city = $this->db()->escape(trim($get['city'])); + $zip = $this->db()->escape(trim($get['zip'])); + $search_cluster_id = $this->db()->escape(trim($get['cluster_id'])); - if(!$search && !$street && !$city && !$zip) { + if(!$search && !$street && !$city && !$zip && !$search_cluster_id) { return mfResponse::BadRequest(['message' => "No search parameters"]); } @@ -151,24 +255,37 @@ class AddressdbApicontroller extends mfBaseApicontroller { $street = $search; } - $street_search = ["name%" => $street]; + $where = "1=1"; + $where .= " AND strasse like '$street%'"; if($city) { - $street_search['gemeinde%'] = $city; + if($this->district_is_city) { + $where .= " AND ortschaft like '$city%'"; + } else { + $where .= " AND gemeinde like '$city%'"; + } } if($zip) { - $street_search['plz%'] = $zip; + $where .= " AND plz like '$zip%'"; } if(count($this->filter_salescluster_ids)) { - $street_search['netzgebiet_id'] = $this->filter_salescluster_ids; + $where .= " AND netzgebiet_id IN (".join(", ", $this->filter_salescluster_ids).")"; } - $results = ADBStrasseModel::search($street_search); - + if($search_cluster_id) { + $where .= " AND netzgebiet_extref='$search_cluster_id'"; + } $streets = []; - foreach($results as $result) { - $streets[] = $result->name; + + $sql = "SELECT strasse FROM view_hausnummer WHERE $where GROUP BY strasse ORDER BY strasse"; + //echo "$sql";exit; + $res = $this->db()->query($sql); + if($this->db()->num_rows($res)) { + while($data = $this->db()->fetch_object($res)) { + $streets[] = $data->strasse; + } + } $streets = array_unique($streets); @@ -176,17 +293,396 @@ class AddressdbApicontroller extends mfBaseApicontroller { return mfResponse::Ok(['streets' => array_values($streets)]); } + protected function search() { + $get = array_merge($this->post, $this->get); + + $search = $this->db()->escape(trim($get['search'])); + + $format = "flat"; + if($get['format'] == "tree") { + $format = "tree"; + } + + if(!$search) { + return mfResponse::BadRequest(['message' => "Search string cannot be empty"]); + } + if($search == "%") { + return mfResponse::BadRequest(['message' => "Search string cannot be empty"]); + } + + /* + * try direct search + */ + /*$m = []; + if(preg_match('/^([^,]+)\s+(\d+\w+),\s*(\d+),?\s*(.+)$/', $search, $m)) { + if($m[1] && $m[2] && $m[3] && $m[4]) { + $dsearch['Strasse.name'] = $this->db()->escape(trim($m[1])); + $dsearch['Hausnummer.hausnummer'] = $this->db()->escape(trim($m[2])); + $dsearch['Plz.plz'] = $this->db()->escape(trim($m[3])); + if($this->district_is_city) { + $dsearch['Ortschaft.name'] = $this->db()->escape(trim($m[4])); + } else { + $dsearch['Gemeinde.name'] = $this->db()->escape(trim($m[4])); + } + + $where = "1=1"; + if(count($this->filter_salescluster_ids)) { + $where .= " AND netzgebiet_id IN (".implode(",", $this->filter_salescluster_ids).")"; + } + foreach($dsearch as $field => $value) { + $where .= " AND $field = '$value'"; + } + + $sql = AddressDB::$wohneinheit_query; + $sql .= "\n WHERE $where"; + $this->log->debug($sql); + + $res = $this->db()->query($sql); + + if($this->db()->num_rows($res)) { + $address = []; + $units = []; + $hausnummer_id = false; + while($data = $this->db()->fetch_object($res)) { + if(!$hausnummer_id) { + $hausnummer_id = $data->hausnummer_id; + + // get allowed preorderTypes + $ptypes = []; + if($data->freigabe) { + $freigaben = json_decode($data->freigabe); + if(is_array($freigaben) && count($freigaben)) { + foreach($freigaben as $freigabe) { + if(in_array($freigabe, $this->allowed_preordertypes)) { + $ptypes[] = $freigabe; + } + } + } + } + + $housenumber = $data->hausnummer; + if($this->hausnummer_add_zusatz) { + if($data->zusatz) { + $housenumber .= " (".$data->zusatz.")"; + } + } + + $address = [ + 'oaid' => $data->hausnummer_oaid, + 'cluster_id' => $data->netzgebiet_extref, + 'zip' => $data->plz, + 'city' => $data->gemeinde, + "municipality" => "", + 'district' => $data->ortschaft, + 'street' => $data->strasse, + 'housenumber' => $housenumber, + 'lot_number' => $data->grund_nr, + 'building_unit_count' => 0, + 'gps_lat' => ($data->gps_lat) ? (float)$data->gps_lat : null, + 'gps_long' => ($data->gps_long) ? (float)$data->gps_long : null, + 'rollout_year' => ($data->rollout) ? (int)$data->rollout : null, + 'rollout_info' => $data->rollout_info, + 'preorderTypes' => $ptypes, + 'units' => [] + ]; + if($this->district_is_city) { + $address['city'] = $data->ortschaft; + $address['municipality'] = $data->gemeinde; + } else { + unset($address['municipality']); + } + } + if($hausnummer_id && $hausnummer_id != $data->hausnummer_id) { + $address = []; + break; + } + + $units[] = [ + 'oaid' => $data->wohneinheit_oaid, + 'num' => (int)$data->num, + 'block' => $data->block, + 'stiege' => $data->stiege, + 'stock' => $data->stock, + 'tuer' => $data->tuer, + 'zusatz' => $data->zusatz, + ]; + } + //var_dump($address, $units);exit; + $new_addresses = []; + if($address) { + if($format == "tree") { + $new_address = $address; + $new_address['units'] = $units; + $new_addresses[] = $address; + } else { + foreach($units as $unit) { + $new_address = $address; + unset($new_address['units']); + $new_address['building_unit_count'] = count($units); + $new_address['num'] = $unit['num']; + $new_address['block'] = $unit['block']; + $new_address['stiege'] = $unit['stiege']; + $new_address['stock'] = $unit['stock']; + $new_address['tuer'] = $unit['tuer']; + $new_address['zusatz'] = $unit['zusatz']; + $new_addresses[] = $new_address; + } + } + + return mfResponse::Ok(['addresses' => $new_addresses]); + + } + + } + } + + + }*/ + + /* + * do normal search + */ + $search_parts = []; + $search = str_replace(",", "", $search); + $tmp_search_parts = explode(" ", $search); + $ort_search = $strasse_search = $plz_search = $hausnummer_search = []; + + foreach($tmp_search_parts as $p) { + $p = $this->db()->escape(trim($p)); + if(!$p) continue; + if(in_array($p,$search_parts)) continue; + $search_parts[] = $p; + $gem_search[] = "Gemeinde.name like '$p%'"; + $ort_search[] = "Ortschaft.name like '$p%'"; + $strasse_search[] = "Strasse.name like '$p%'"; + $plz_search[] = "Plz.plz like '$p%'"; + $hausnummer_search[] = "Hausnummer.hausnummer like '$p%'"; + } + + $where = "1=1"; + if(count($this->filter_salescluster_ids)) { + $where .= " AND netzgebiet_id IN (".implode(",", $this->filter_salescluster_ids).")"; + } + + $sql = AddressDB::$wohneinheit_query; + $sql .= "\n WHERE $where AND ((".implode(" OR ", $ort_search).") OR (".implode(" OR ", $strasse_search).") OR (".implode(" OR ", $plz_search).") OR (".implode(" OR ", $hausnummer_search).")) ORDER BY strasse, LENGTH(hausnummer), hausnummer, LENGTH(tuer),tuer, zusatz, LENGTH(num), num"; + + //$sql = "SELECT * FROM view_wohneinheit WHERE $where AND ((".implode(" OR ", $ort_search).") OR (".implode(" OR ", $strasse_search).") OR (".implode(" OR ", $plz_search).") OR (".implode(" OR ", $hausnummer_search).")) ORDER BY strasse, LENGTH(hausnummer), hausnummer, LENGTH(tuer),tuer, zusatz, LENGTH(num), num"; + $this->log->debug($sql); + + $res = $this->db()->query($sql); + + + + if($this->db()->num_rows($res)) { + $tmp_addresses = []; + while($data = $this->db()->fetch_object($res)) { + $address_key = $data->hausnummer_id; + if($this->hausnummer_add_zusatz) { + $address_key = $data->hausnummer_id."-".$data->zusatz; + } + //$sort_key = $data->plz." ".$data->gemeinde." ".$data->ortschaft." ".$data->strasse." ".$data->hausnummer." ".$data->zusatz; + $sort_key = $data->plz." ".$data->gemeinde." ".$data->ortschaft." ".$data->strasse." ".$data->hausnummer." ".$data->zusatz; + if(!array_key_exists($address_key, $tmp_addresses)) { + + // get allowed preorderTypes + $ptypes = []; + if($data->freigabe) { + $freigaben = json_decode($data->freigabe); + if(is_array($freigaben) && count($freigaben)) { + foreach($freigaben as $freigabe) { + if(in_array($freigabe, $this->allowed_preordertypes)) { + $ptypes[] = $freigabe; + } + } + } + } + + $housenumber = $data->hausnummer; + if($this->hausnummer_add_zusatz) { + if($data->zusatz) { + $housenumber .= " (".$data->zusatz.")"; + } + } + + $tmp_addresses[$address_key] = [ + 'sort_key' => $sort_key, + 'oaid' => $data->hausnummer_oaid, + 'cluster_id' => $data->netzgebiet_extref, + 'zip' => $data->plz, + 'city' => $data->gemeinde, + "municipality" => "", + 'district' => $data->ortschaft, + 'street' => $data->strasse, + 'housenumber' => $housenumber, + 'lot_number' => $data->grund_nr, + 'building_unit_count' => 0, + 'gps_lat' => ($data->gps_lat) ? (float)$data->gps_lat : null, + 'gps_long' => ($data->gps_long) ? (float)$data->gps_long : null, + 'rollout_year' => ($data->rollout) ? (int)$data->rollout : null, + 'rollout_info' => $data->rollout_info, + 'preorderTypes' => $ptypes, + 'units' => [] + ]; + if($this->district_is_city) { + $tmp_addresses[$address_key]['city'] = $data->ortschaft; + $tmp_addresses[$address_key]['municipality'] = $data->gemeinde; + } else { + unset($tmp_addresses[$address_key]['municipality']); + } + } + + $tmp_addresses[$address_key]['units'][] = [ + 'oaid' => $data->wohneinheit_oaid, + 'num' => (int)$data->num, + 'block' => $data->block, + 'stiege' => $data->stiege, + 'stock' => $data->stock, + 'tuer' => $data->tuer, + 'zusatz' => $data->zusatz, + ]; + $tmp_addresses[$address_key]['building_unit_count']++; + //if($data->hausnummer_oaid == "AT-8940-30400d5c") var_dump($data); + } + //exit; + //var_dump($tmp_addresses);exit; + // sort found addresses by count of found keywords + // if there is an int we don't want to show more than one street + $sorted_addresses = []; + foreach($tmp_addresses as $temp_add) { + $includes_int = false; + $count = 0; + $count_parts = 0; + $uniq_parts_count = 0; + $uniq_parts_found = []; + /*if($temp_add['oaid'] == "AT-8940-30400d5c") { + var_dump($temp_add); + }*/ + foreach($search_parts as $p) { + $p = $this->db->escape(trim($p)); + if(strlen($p) === 0) continue; + $uniq_parts_count++; + if(is_numeric(($p))) { + $includes_int = true; + $count_parts++; + if(substr_count(strtolower($temp_add['sort_key']), strtolower($p))) { + $count++; + } + if(!in_array($p, $uniq_parts_found)) { + $uniq_parts_found[] = $p; + } + } else { + $p_count = substr_count(strtolower($temp_add['sort_key']), strtolower($p)); + if($p_count) { + $count += $p_count; + $count_parts++; + if(!in_array($p, $uniq_parts_found)) { + $uniq_parts_found[] = $p; + } + } + } + } + + unset($temp_add['sort_key']); + if($includes_int && (($count + 1) - count($search_parts) ) < 1) { + continue; + } + + //var_dump(count($search_parts), $count, $count_parts, $temp_add); + + /*if($temp_add['oaid'] == "AT-8954-d6c41665") { + echo $temp_add['sort_key'].": AT-8954-d6c41665: count $count; uniq_parts_count $uniq_parts_count; count_parts $count_parts; search_parts ".count($search_parts)."

    \n"; + //var_dump(); + //exit; + }*/ + + if($count_parts == count($search_parts)) { + $count += 50; + } + + if($uniq_parts_count <= count($uniq_parts_found)) { + if(!array_key_exists($count, $sorted_addresses)) { + $sorted_addresses[$count] = []; + } + $sorted_addresses[$count][] = $temp_add; + } + } + //exit; + + + ksort($sorted_addresses, SORT_NUMERIC); + $sorted_addresses = array_reverse($sorted_addresses, true); + //var_dump($sorted_addresses);exit; + + // sort / format + if($format == "tree") { + foreach($sorted_addresses as $counted_addresses) { + foreach($counted_addresses as $cadd) { + $addresses[] = $cadd; + } + } + //var_dump($addresses);exit; + //$addresses = array_values($sorted_addresses); + + if(!$addresses) $addresses = []; + } else { + foreach($sorted_addresses as $counted_addresses) { + foreach($counted_addresses as $ta) { + foreach($ta['units'] as $u) { + $new_address = []; + $new_address['oaid'] = $u['oaid']; + $new_address['building_oaid'] = $ta['oaid']; + $new_address['cluster_id'] = $ta['cluster_id']; + $new_address['street'] = $ta['street']; + $new_address['housenumber'] = $ta['housenumber']; + $new_address['zip'] = $ta['zip']; + $new_address['city'] = $ta['city']; + if(array_key_exists("municipality", $ta)) { + $new_address['municipality'] = $ta['municipality']; + } + $new_address['district'] = $ta['district']; + $new_address['lot_number'] = $ta['lot_number']; + $new_address['building_unit_count'] = $ta['building_unit_count']; + $new_address['num'] = $u['num']; + $new_address['block'] = $u['block']; + $new_address['stiege'] = $u['stiege']; + $new_address['stock'] = $u['stock']; + $new_address['tuer'] = $u['tuer']; + $new_address['zusatz'] = $u['zusatz']; + $new_address['gps_lat'] = $ta['gps_lat']; + $new_address['gps_long'] = $ta['gps_long']; + $new_address['rollout_year'] = $ta['rollout_year']; + $new_address['rollout_info'] = $ta['rollout_info']; + $new_address['preorderTypes'] = $ta['preorderTypes']; + + $addresses[] = $new_address; + } + } + } + } + + } + + return mfResponse::Ok(['addresses' => $addresses]); + } + protected function find() { // unofficially supporting GET and POST in v1 $get = array_merge($this->post, $this->get); + $search_cluster_id = $this->db()->escape(trim($get['cluster_id'])); $search_street = $this->db()->escape(trim($get['street'])); $search_zip = $this->db()->escape(trim($get['zip'])); + $search_district = $this->db()->escape(trim($get['district'])); $search_city = $this->db()->escape(trim($get['city'])); $search_housenumber = $this->db()->escape(trim($get['housenumber'])); + $format = "flat"; + if($get['format'] == "tree") { + $format = "tree"; + } - if(!$search_street) { + if(!$search_street && !$search_cluster_id) { return mfResponse::BadRequest(['message' => "Searchstring cannot be empty!"]); } @@ -194,54 +690,148 @@ class AddressdbApicontroller extends mfBaseApicontroller { $where = "1=1"; - if($search_zip) { - $where .= " AND plz like '%$search_zip%'"; + if($search_zip && $search_zip != "%") { + $where .= " AND Plz.plz like '$search_zip%'"; } - if($search_city) { - $where .= " AND gemeinde like '%$search_city%'"; + if($search_district && $search_district != "%") { + $where .= " AND Ortschaft.name like '$search_district%'"; } - if($search_street) { - $where .= " AND strasse like '%$search_street%'"; + if($search_city && $search_city != "%") { + if($this->district_is_city) { + $where .= " AND Ortschaft.name like '$search_city%'"; + } else { + $where .= " AND Gemeinde.name like '$search_city%'"; + } } - if($search_housenumber) { - $where .= " AND hausnummer like '%$search_housenumber%'"; + if($search_street && $search_street != "%") { + $where .= " AND Strasse.name like '$search_street%'"; } - - $sql = "SELECT * FROM view_wohneinheit WHERE $where ORDER BY plz, gemeinde, ortschaft, strasse, LENGTH(hausnummer), hausnummer, block, stiege, stock, LENGTH(tuer), tuer"; + if($search_housenumber && $search_housenumber != "%") { + $where .= " AND Hausnummer.hausnummer like '$search_housenumber%'"; + } + + if(count($this->filter_salescluster_ids)) { + $where .= " AND Hausnummer.netzgebiet_id IN (".implode(",", $this->filter_salescluster_ids).")"; + } + if($search_cluster_id) { + $where .= " AND Netzgebiet.extref='$search_cluster_id'"; + } + //echo $where; + //var_dump($this->filter_salescluster_ids);exit; + + $sql = AddressDB::$wohneinheit_query; + $sql .= "\n WHERE $where ORDER BY plz, gemeinde, ortschaft, strasse, LENGTH(hausnummer), hausnummer, block, stiege, stock, LENGTH(num), num, LENGTH(tuer), tuer"; + + //$sql = "SELECT * FROM view_wohneinheit WHERE $where ORDER BY plz, gemeinde, ortschaft, strasse, LENGTH(hausnummer), hausnummer, block, stiege, stock, LENGTH(num), num, LENGTH(tuer), tuer"; + $this->log->debug($sql); $res = $this->db()->query($sql); if($this->db()->num_rows($res)) { - while($data = $this->db()->fetch_object($res)) { - - // get allowed preorderTypes - $ptypes = []; - if($data->freigabe) { - $freigaben = json_decode($data->freigabe); - if(is_array($freigaben) && count($freigaben)) { - foreach($freigaben as $freigabe) { - if(in_array($freigabe, $this->allowed_preordertypes)) { - $ptypes[] = $freigabe; + $tmp_addresses = []; + while($data = $this->db()->fetch_object($res)) { + $address_key = $data->hausnummer_id; + if($this->hausnummer_add_zusatz) { + $address_key = $data->hausnummer_id."-".$data->zusatz; + } + if(!array_key_exists($address_key, $tmp_addresses)) { + + // get allowed preorderTypes + $ptypes = []; + if($data->freigabe) { + $freigaben = json_decode($data->freigabe); + if(is_array($freigaben) && count($freigaben)) { + foreach($freigaben as $freigabe) { + if(in_array($freigabe, $this->allowed_preordertypes)) { + $ptypes[] = $freigabe; + } + } } } + + $housenumber = $data->hausnummer; + if($this->hausnummer_add_zusatz) { + if($data->zusatz) { + $housenumber .= " (".$data->zusatz.")"; + } + } + + $tmp_addresses[$address_key] = [ + 'oaid' => $data->hausnummer_oaid, + 'cluster_id' => $data->netzgebiet_extref, + 'zip' => $data->plz, + 'city' => $data->gemeinde, + "municipality" => "", + 'district' => $data->ortschaft, + 'street' => $data->strasse, + 'housenumber' => $housenumber, + 'lot_number' => $data->grund_nr, + 'building_unit_count' => 0, + 'gps_lat' => ($data->gps_lat) ? (float)$data->gps_lat : null, + 'gps_long' => ($data->gps_long) ? (float)$data->gps_long : null, + 'rollout_year' => ($data->rollout) ? (int)$data->rollout : null, + 'rollout_info' => $data->rollout_info, + 'preorderTypes' => $ptypes, + 'units' => [] + ]; + if($this->district_is_city) { + $tmp_addresses[$address_key]['city'] = $data->ortschaft; + $tmp_addresses[$address_key]['municipality'] = $data->gemeinde; + } else { + unset($tmp_addresses[$address_key]['municipality']); + } + } + + $tmp_addresses[$address_key]['units'][] = [ + 'oaid' => $data->wohneinheit_oaid, + 'num' => (int)$data->num, + 'block' => $data->block, + 'stiege' => $data->stiege, + 'stock' => $data->stock, + 'tuer' => $data->tuer, + 'zusatz' => $data->zusatz, + ]; + $tmp_addresses[$address_key]['building_unit_count']++; + + } + if($format == "tree") { + /*foreach($tmp_addresses as $ta) { + $addresses[] = $ta; + }*/ + $addresses = array_values($tmp_addresses); + } else { + foreach($tmp_addresses as $ta) { + foreach($ta['units'] as $u) { + $new_address = []; + $new_address['oaid'] = $u['oaid']; + $new_address['building_oaid'] = $ta['oaid']; + $new_address['cluster_id'] = $ta['cluster_id']; + $new_address['street'] = $ta['street']; + $new_address['housenumber'] = $ta['housenumber']; + $new_address['zip'] = $ta['zip']; + $new_address['city'] = $ta['city']; + if(array_key_exists("municipality", $ta)) { + $new_address['municipality'] = $ta['municipality']; + } + $new_address['district'] = $ta['district']; + $new_address['lot_number'] = $ta['lot_number']; + $new_address['building_unit_count'] = $ta['building_unit_count']; + $new_address['num'] = $u['num']; + $new_address['block'] = $u['block']; + $new_address['stiege'] = $u['stiege']; + $new_address['stock'] = $u['stock']; + $new_address['tuer'] = $u['tuer']; + $new_address['zusatz'] = $u['zusatz']; + $new_address['gps_lat'] = $ta['gps_lat']; + $new_address['gps_long'] = $ta['gps_long']; + $new_address['rollout_year'] = $ta['rollout_year']; + $new_address['rollout_info'] = $ta['rollout_info']; + $new_address['preorderTypes'] = $ta['preorderTypes']; + + $addresses[] = $new_address; + } } } - - $addresses[] = [ - 'zip' => $data->plz, - 'city' => $data->gemeinde, - 'street' => $data->strasse, - 'housenumber' => $data->hausnummer, - 'block' => $data->block, - 'stock' => $data->stock, - 'stiege' => $data->stiege, - 'tuer' => $data->tuer, - 'zusatz' => $data->zusatz, - 'gps_lat' => $data->gps_lat, - 'gps_long' => $data->gps_long, - 'rollout_year' => ($data->rollout) ? (int)$data->rollout : null, - 'preorderTypes' => $ptypes - ]; - } + } return mfResponse::Ok(['addresses' => $addresses]); diff --git a/application/Api/v1/PreorderApicontroller.php b/application/Api/v1/PreorderApicontroller.php index 3fd9dc7cf..4c47c202f 100644 --- a/application/Api/v1/PreorderApicontroller.php +++ b/application/Api/v1/PreorderApicontroller.php @@ -10,12 +10,18 @@ class PreorderApicontroller extends mfBaseApicontroller { private $campaigns_by_scluster = []; private $allowed_preordertypes = []; - + private $district_is_city = false; + private $hausnummer_add_zusatz = false; + private $exist_is_error = false; + private $require_connectiontype = false; + private $allow_unit_update = false; protected function init() { $db = $this->db(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME); $this->addRoute("/preorder", "submitPreorder", "POST"); + $this->addRoute("/preorder/:code", "getPreorder", "GET"); + $this->addRoute("/preorder/:code", "cancelPreorder", "DELETE"); $this->allowMissingOrigin = true; } @@ -42,7 +48,26 @@ class PreorderApicontroller extends mfBaseApicontroller { $this->allowed_preordertypes[] = $type->type; } } + + if($campaign->district_is_city == 1) { + $this->district_is_city = true; + } + if($campaign->hausnummer_add_zusatz == 1) { + $this->hausnummer_add_zusatz = true; + } + if($campaign->exist_is_error == 1) { + $this->exist_is_error = true; + } + if($campaign->require_connectiontype == 1) { + $this->require_connectiontype = true; + } + if($campaign->allow_unit_update == 1) { + $this->allow_unit_update = true; + } + } + + foreach(PreordercampaignOriginhostnameModel::search(['preordercampaign_id' => $campaign->id]) as $origin) { $this->addAllowedOrigin($origin->hostname); @@ -54,7 +79,76 @@ class PreorderApicontroller extends mfBaseApicontroller { //var_dump($campaign, $this->allowed_origins);exit; } + protected function getPreorder($code) { + $code = trim(strtoupper($code)); + if(!$code) { + return mfResponse::NotFound(["message" => "Preorder not found"]); + } + + $preorder = PreorderModel::getFirst(['ucode' => $code]); + if(!$preorder) { + // try oan id + $preorder = PreorderModel::getFirst(['oaid' => $code]); + if(!$preorder) { + return mfResponse::NotFound(["message" => "Preorder not found"]); + } + } + + if($preorder->partner_id != $this->me->address_id) { + return mfResponse::NotFound(["message" => "Preorder not found"]); + } + + $return = $preorder->getApiArray(); + if(!$return) { + return mfResponse::NotFound(["message" => "Preorder not found"]); + } + + + return mfResponse::Ok($return); + + } + + protected function cancelPreorder($code) { + $code = trim(strtoupper($code)); + if(!$code) { + return mfResponse::NotFound(["message" => "Preorder not found"]); + } + + $preorder = PreorderModel::getFirst(['ucode' => $code, 'partner_id' => $this->me->address_id, 'deleted' => 0, ' 800]); + if(!$preorder) { + // try oan id + $preorder = PreorderModel::getFirst(['oaid' => $code, 'partner_id' => $this->me->address_id, 'deleted' => 0, ' 800]); + if(!$preorder) { + return mfResponse::NotFound(["message" => "Preorder not found or cancelled already"]); + } + } + + // check if user owns preorder + if($preorder->partner_id != $this->me->address_id) { + return mfResponse::Forbidden(["message" => "Permission denied"]); + } + + if($preorder->cancel_request) { + if($preorder->cancel_approved) { + return mfResponse::Forbidden(["message" => "Order already cancelled"]); + } else { + return mfResponse::Forbidden(["message" => "Cancellation request was already submitted"]); + } + } + + // set cancel_date and canceller + $preorder->cancel_request = date('U'); + $preorder->cancel_request_by = $this->me->id; + if(!$preorder->save()) { + return mfResponse::InternalServerError(); + } + + return mfResponse::Ok(['message' => "Cancellation request submited"]); + + } + protected function submitPreorder() { + //var_dump($this->post);exit; if(!$this->campaigns) { $this->log->debug("disallowed request because no campaign for apikey"); return mfResponse::Forbidden(); @@ -65,7 +159,7 @@ class PreorderApicontroller extends mfBaseApicontroller { return mfResponse::BadRequest(["message" => "Invalid preorderType"]); } - $connection_type = false; + $connection_type = null; switch($this->post['connectionType']) { case "single-dwelling": $connection_type = "single-dwelling"; @@ -83,7 +177,9 @@ class PreorderApicontroller extends mfBaseApicontroller { $connection_type = "business"; break; default: - return mfResponse::BadRequest(["message" => "Invalid connectionType"]); + if($this->require_connectiontype) { + return mfResponse::BadRequest(["message" => "Invalid connectionType"]); + } } @@ -95,7 +191,12 @@ class PreorderApicontroller extends mfBaseApicontroller { return mfResponse::BadRequest(['message' => "customer data missing"]); } - /* + $is_additional_order = false; + if(array_key_exists("isAdditionalOrder", $this->post) && $this->post['isAdditionalOrder']) { + $is_additional_order = true; + } + + /************************************************************ * check address */ if(!property_exists($this->post['address'],"street") || !$this->post['address']->street || @@ -106,20 +207,48 @@ class PreorderApicontroller extends mfBaseApicontroller { return mfResponse::BadRequest(['message' => "Mandatory address fields missing"]); } + $shipping_address = "customer"; + if(property_exists($this->post['address'], "is_shipping") && $this->post['address']->is_shipping) { + $shipping_address = "address"; + } + $address_search = []; - foreach(['street' => 'strasse','housenumber' => "hausnummer",'zip' => "plz",'city' => "gemeinde"] as $key => $field_name) { + $address_search_fields = [ + 'street' => 'strasse', + 'housenumber' => "hausnummer", + 'zip' => "plz" + ]; + if($this->district_is_city) { + $address_search_fields['city'] = "ortschaft"; + } else { + $address_search_fields['city'] = "gemeinde"; + } + + foreach($address_search_fields as $key => $field_name) { if(property_exists($this->post['address'], $key)) { $address_search[$field_name] = $this->db()->escape(trim($this->post['address']->$key)); } } + $zusatz = false; + if($this->hausnummer_add_zusatz) { + $m = []; + if(preg_match('/^(.*) \((.+)\)$/', trim($address_search['hausnummer']), $m)) { + $address_search['hausnummer'] = $this->db()->escape($m[1]); + $zusatz = $m[2]; + } + } + $unit_search = []; - foreach(['block','stiege','stock','tuer'] as $key) { + foreach(['block','stiege','stock','tuer','unit_string'] as $key) { if(property_exists($this->post['address'], $key) && trim($this->post['address']->$key)) { $unit_search[$key] = trim($this->post['address']->$key); } } - + if($zusatz) { + $unit_search['zusatz'] = $zusatz; + } + /* * check customer */ @@ -134,7 +263,7 @@ class PreorderApicontroller extends mfBaseApicontroller { return mfResponse::BadRequest(['message' => "Mandatory customer fields missing"]); } - /* + /************************************************************** * search address in AddressDB */ $where = "1=1 "; @@ -148,54 +277,83 @@ class PreorderApicontroller extends mfBaseApicontroller { } $sql = "SELECT * FROM view_hausnummer WHERE $where"; + $this->log->debug($sql); $res = $this->db()->query($sql); if(!$this->db()->num_rows($res)) { - //var_dump($this->db()->num_rows($res), $this->db()->fetch_object($res)); return mfResponse::NotFound(['message' => "Adresse nicht gefunden"]); } $address = $this->db()->fetch_object($res); + //var_dump($address);exit; - - /* + /* ************************************************************** * search wohneinheit */ + $update_unit = false; + $assign_unit = false; + $where = "1=1 "; $unit = false; if(count($unit_search)) { - foreach($unit_search as $field => $value) { - if($field == "stock" || $field == "stiege") continue; // only check for block and tuer - $where .= " AND `$field` = '$value'"; + //var_dump($unit_search);exit; + if(array_key_exists("unit_string", $unit_search)) { + $where .= " AND bezeichner LIKE '".$unit_search['unit_string']."'"; + } else { + foreach($unit_search as $field => $value) { + if($field == "stock") continue; // only check for block, stiege and tuer + $where .= " AND `$field` = '$value'"; + } } - // filter salesclusters if(count($this->filter_salescluster_ids)) { $where .= " AND netzgebiet_id IN (".implode(',', $this->filter_salescluster_ids).")"; } - $sql = "SELECT * FROM view_wohneinheit WHERE 1=1 $where AND hausnummer_id=".$address->hausnummer_id; + $sql = "SELECT * FROM view_wohneinheit WHERE $where AND hausnummer_id=".$address->hausnummer_id; + $this->log->debug($sql); $res = $this->db()->query($sql); if($this->db()->num_rows($res)) { $unit = $this->db()->fetch_object($res); - //return mfResponse::NotFound(['message' => "Wohneinheit nicht gefunden"]); + } else { + $update_unit = true; } - //var_dump($this->db()->num_rows($res), $this->db()->fetch_object($res)); } else { // if all unit values are empty try to find the unit with all empty values // failure is not an error, but must be checked by a human at some point - - $where = "hausnummer_id=".$address->hausnummer_id." AND (block = '' OR block IS NULL) AND (stiege = '' OR stiege IS NULL) AND (stock = '' OR stock IS NULL) AND (tuer = '' OR tuer IS NULL)"; + $where = "hausnummer_id=".$address->hausnummer_id." AND (block = '' OR block IS NULL) AND (stiege = '' OR stiege IS NULL) AND (stock = '' OR stock IS NULL) AND (tuer = '' OR tuer IS NULL) AND (bezeichner = '' OR bezeichner IS NULL)"; + if($zusatz) { + $where .= " AND zusatz='$zusatz'"; + } else { + $where .= " AND (zusatz = '' OR zusatz IS NULL)"; + } // filter salesclusters if(count($this->filter_salescluster_ids)) { $where .= " AND netzgebiet_id IN (".implode(',', $this->filter_salescluster_ids).")"; } $sql = "SELECT * FROM view_wohneinheit WHERE $where"; + $this->log->debug($sql); $res = $this->db()->query($sql); if($this->db()->num_rows($res)) { $unit = $this->db()->fetch_object($res); + } else { + // XXX + //$assign_unit = true; } } + if($this->exist_is_error && !$is_additional_order) { + /* + * check if there is an existing preorder for this unit already + */ + if($unit && $unit->wohneinheit_id) { + $existing_preorder = PreorderModel::getFirst(['adb_wohneinheit_id' => $unit->wohneinheit_id, 'deleted' => 0]); + if($existing_preorder) { + return mfResponse::Forbidden(['message' => "Für diese Wohneinheit liegt bereits eine Bestellung vor"]); + } + } + } + + $address_info = $this->db()->escape(trim($this->post['address_info'])); // get correct campaign by salescluster @@ -206,6 +364,10 @@ class PreorderApicontroller extends mfBaseApicontroller { $campaign_id = $this->campaigns_by_scluster[$address->netzgebiet_id]; $this->campaign = new Preordercampaign($campaign_id); + if($this->campaign->from > date('U') || $this->campaign->to < date('U')) { + return mfResponse::Forbidden(['message' => "Bestellung in diesem Netzgebiet/Cluster nicht erlaubt"]); + } + /* * build fields */ @@ -219,13 +381,18 @@ class PreorderApicontroller extends mfBaseApicontroller { $preorder_data['submit_request'] = $this->request_json; } $preorder_data['adb_hausnummer_id'] = $address->hausnummer_id; + $preorder_data['partner_id'] = $this->me->address_id; if($unit) { $preorder_data['adb_wohneinheit_id'] = $unit->wohneinheit_id; + $preorder_data['oaid'] = $unit->wohneinheit_oaid; } if($address_info) { $preorder_data['address_info'] = $address_info; } + if(property_exists($this->post['address'],"district") && $this->post['address']->district) { + $preorder_data['address_district'] = $this->post['address']->district; + } if($this->post['acceptAgb'] === true) { $preorder_data['accept_agb'] = 1; @@ -240,6 +407,14 @@ class PreorderApicontroller extends mfBaseApicontroller { $preorder_data['accept_withdrawal'] = 1; } + if($is_additional_order) { + $preorder_data['is_additional_order'] = 1; + } else { + $preorder_data['is_additional_order'] = 0; + } + $preorder_data['technology'] = ($this->post['technology']) ? $this->post['technology'] : null; + $preorder_data['patchposition'] = ($this->post['patchposition']) ? $this->post['patchposition'] : null; + /* * setup price */ @@ -281,9 +456,9 @@ class PreorderApicontroller extends mfBaseApicontroller { /* * get customer data */ - foreach(['company','uid','firstname','lastname','street','zip','city','phone','email'] as $key) { + foreach(['company','uid','firstname','lastname','street','housenumber','zip','city','phone','email','block','stiege','stock','tuer', 'unit_string'] as $key) { if(property_exists($customer, $key)) { - $preorder_data[$key] = $customer->$key; + $preorder_data[$key] = ($customer->$key) ? $customer->$key : null; } } @@ -322,6 +497,103 @@ class PreorderApicontroller extends mfBaseApicontroller { } } + + + + //var_dump($this->allow_unit_update, $update_unit);exit; + + /************************************************** + * update wohneinheit if allowed + * and unit search data was submitted + */ + + $unit_changed = false; + + if($this->allow_unit_update && $update_unit) { + //var_dump($unit_search); + //var_dump($unit); + //exit; + + // get available units + $exclude_wohneinheit_ids = []; + $preorders_in_hausnummer = PreorderModel::search(['adb_hausnummer_id' => $address->hausnummer_id]); + if(count($preorders_in_hausnummer)) { + + foreach($preorders_in_hausnummer as $pih) { + if($pih->adb_wohneinheit_id) { + $exclude_wohneinheit_ids[] = $pih->adb_wohneinheit_id; + } + } + } + // get units excluding unavailable units + $where = "hausnummer_id=".$address->hausnummer_id; + $where .= " AND ( block = '' OR block IS NULL)"; + $where .= " AND ( stiege = '' OR stiege IS NULL)"; + $where .= " AND ( stock = '' OR stock IS NULL)"; + $where .= " AND ( tuer = '' OR tuer IS NULL)"; + $where .= " AND ( bezeichner = '' OR bezeichner IS NULL)"; + + if(count($exclude_wohneinheit_ids)) { + $where .= " AND wohneinheit_id NOT IN (". implode(",",$exclude_wohneinheit_ids).")"; + } + $sql = "SELECT * FROM view_wohneinheit WHERE $where"; + $this->log->debug($sql); + $res = $this->db()->query($sql); + if(!$this->db()->num_rows($res)) { + return mfResponse::Forbidden(['message' => "Keine Wohneinheiten verfügbar"]); + } + + $unit_row = $this->db()->fetch_object($res); + $unit = new ADBWohneinheit($unit_row->wohneinheit_id); + if(!$unit->id) { + return mfResponse::InternalServerError(['message' => "unit not found"]); + } + //echo "blah";exit; + + $change_note_data = []; + foreach(['block','stiege','stock','tuer','bezeichner'] as $unit_address_part) { + if($unit_search[$unit_address_part]) { + $unit->$unit_address_part = $unit_search[$unit_address_part]; + $unit_changed = true; + $change_note_data[] = [ + 'field' => $unit_address_part, + 'from' => $unit->_old_data->$unit_address_part, + 'to' => $unit_search[$unit_address_part] + ]; + } + } + + if($unit_changed) { + $change_note_text = ($unit->note) ? $unit->note : ""; + $change_note_text .= date("Y-m-d H:i:s").": "; + foreach($change_note_data as $cn) { + $field = $cn['field']; + $from = ($cn['from'] === null) ? "NULL" : "'".$cn['from']."'"; + $to = ($cn['to'] === null) ? "NULL" : "'".$cn['to']."'"; + $change_note_text .= "$field from $from to $to; "; + } + $change_note_text .= "\n"; + $unit->note = $change_note_text; + + $unit->startTransaction(); + $unit->save(); + } + //var_dump($unit);exit; + + $preorder_data['adb_wohneinheit_id'] = $unit->id; + $preorder_data['oaid'] = $unit->oaid; + } + + + // assign next wohneinheit if no unit search data was submitted + /* + if($this->allow_unit_update && $assign_unit) { + var_dump($unit_search); + var_dump($unit); + exit; + }*/ + + /* * create preorder record */ @@ -331,10 +603,21 @@ class PreorderApicontroller extends mfBaseApicontroller { $preorder_id = $preorder->save(); if(!$preorder_id || !$preorder->ucode) { + if($unit_changed) $unit->rollbackTransaction(); return mfResponse::InternalServerError(); } - return mfResponse::Ok(["code" => $preorder->ucode]); + if($unit_changed) $unit->commitTransaction(); + + $return = ["code" => $preorder->ucode]; + if($preorder->oaid) { + $return ['oaid'] = $preorder->oaid; + } + if($addon_data) { + $return["additionalData"] = $addon_data; + } + + return mfResponse::Ok($return); } } \ No newline at end of file diff --git a/application/Building/BuildingController.php b/application/Building/BuildingController.php index 47b504580..7eb87b9b1 100644 --- a/application/Building/BuildingController.php +++ b/application/Building/BuildingController.php @@ -372,14 +372,56 @@ class BuildingController extends mfBaseController { private function getFilteredBuildingsApi() { $buildings = []; - $filter = $this->request->filter; + $filter = []; + if(is_array($this->request->filter)) { + $filter = $this->request->filter; + } + if(!$this->me->is("Admin")) { + $my_networks = $this->me->myNetworks(['netowner','salespartner']); + + $network_ids = []; + foreach($my_networks as $net) { + $network_ids[] = $net->id; + } + + if(array_key_exists("network_id", $filter)) { + if(!in_array($filter['network_id'], $network_ids)) { + $filter['network_id'] = $network_ids; + } + } else { + $filter['network_id'] = $network_ids; + } + } $results = BuildingModel::search($filter); foreach($results as $building) { - $data = $building->data; + //$this->log->debug("building status: ".print_r($building->status,true)); + $data = clone($building->data); $data->id = $building->id; + $data->status = "none"; + $data->type = $building->type->name; + $data->popname = ($building->pop_id) ? $building->pop->name : "-"; + + $terms = []; + foreach($building->terminations as $term) { + $building_term = []; + $building_term['id'] = $term->id; + $building_term['status'] = "none"; + + //$this->log->debug("building status: ".print_r($building->status,true)); + if($term->status->code == TT_TERMSTATUS_CONNECTED) { + $building_term['status'] = "connected"; + $data->status = "connected"; + } elseif($building->status->code == TT_BUILDINGSTATUS_CONNECTED) { + $building_term['status'] = "pipework-done"; + if($data->status != "connected") $data->status = "pipework-done"; + } + $terms[] = $building_term; + } + + $data->terminations = $terms; $buildings[] = $data; } diff --git a/application/Building/BuildingModel.php b/application/Building/BuildingModel.php index 282392876..1a634382c 100644 --- a/application/Building/BuildingModel.php +++ b/application/Building/BuildingModel.php @@ -54,7 +54,7 @@ class BuildingModel { return $model; } - public static function getFirst() { + public static function getFirst($filter = []) { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); @@ -105,7 +105,7 @@ class BuildingModel { return 0; } - public static function search($filter, $limit = false) { + public static function search($filter=[], $limit = false) { $items = []; $db = FronkDB::singleton(); @@ -168,7 +168,7 @@ class BuildingModel { } } - if(is_array($filter['type']) && count($filter['type'])) { + if(array_key_exists("type", $filter) && is_array($filter['type']) && count($filter['type'])) { $ot = $filter['type']; $in = []; foreach($ot as $type) { diff --git a/application/Contract/Contract.php b/application/Contract/Contract.php index 2607c62ac..50c120017 100644 --- a/application/Contract/Contract.php +++ b/application/Contract/Contract.php @@ -2,22 +2,126 @@ class Contract extends mfBaseModel { private $owner; - private $creator; + private $billingaddress; private $product; private $orderproduct; private $termination; private $sla; + private $contractConfigGroups; + private $contractConfigItems; + private $configgroups; + private $isCancelled; + private $links; + private $linkFrom; + private $linkTo; + private $upgradeFrom; + private $upgradeTo; + private $downgradeFrom; + private $downgradeTo; + private $productchangeFrom; + private $productchangeTo; + private $relocationFrom; + private $relocationTo; + private $finisher; + private $canceler; + private $creator; private $editor; + private function getLinks() { + $this->linkFrom = []; + $this->linkTo = []; + $this->upgradeFrom = []; + $this->upgradeTo = []; + $this->downgradeFrom = []; + $this->downgradeTo = []; + $this->productchangeFrom = []; + $this->productchangeTo = []; + $this->relocationFrom = []; + $this->relocationTo = []; + + // Links targeting this contract (to) + foreach(ContractLinkModel::search(['origin_contract_id' => $this->id]) as $link) { + switch($link->type) { + case "link": + $this->linkTo[] = $link; + break; + case "upgrade": + $this->upgradeTo[] = $link; + break; + case "downgrade": + $this->downgradeTo[] = $link; + break; + case "productchange": + $this->productchangeTo[] = $link; + break; + case "relocation": + $this->relocationTo[] = $link; + break; + default: + $this->log->warn("ContractLink with invalid type: ".$link->id." ".$link->type); + break; + } + } + + foreach(ContractLinkModel::search(['contract_id' => $this->id]) as $link) { + switch($link->type) { + case "link": + $this->linkFrom[] = $link; + break; + case "upgrade": + $this->upgradeFrom[] = $link; + break; + case "downgrade": + $this->downgradeFrom[] = $link; + break; + case "productchange": + $this->productchangeFrom[] = $link; + break; + case "relocation": + $this->relocationFrom[] = $link; + break; + default: + $this->log->warn("ContractLink with invalid type: ".$link->id." ".$link->type); + break; + } + } + + } + + + public function isCancelled() { + if(!$this->id) { + return false; + } + + if(!$this->cancel_date) { + return false; + } + + $now = date('U'); + if($this->cancel_date <= $now) { + return true; + } + + return false; + } + public function getProperty($name) { if($this->$name == null) { - if(!$this->id) { - return null; + if($name == "billingaddress" && $this->billingaddress_id) { + $this->billingaddress = mfValuecache::singleton()->get("mfObjectmodel-Address-".$this->billingaddress_id); + if($this->billingaddress === null) { + $this->billingaddress = new Address($this->billingaddress_id); + if($this->billingaddress->id) { + mfValuecache::singleton()->set("mfObjectmodel-Address-".$this->billingaddress_id, $this->billingaddress); + } + } + return $this->billingaddress; } - if($name == "owner") { + if($name == "owner" && $this->owner_id) { $this->owner = mfValuecache::singleton()->get("mfObjectmodel-Address-".$this->owner_id); if($this->owner === null) { $this->owner = new Address($this->owner_id); @@ -28,17 +132,12 @@ class Contract extends mfBaseModel { return $this->owner; } - if($name == "billingaddress") { - $this->billingaddress = mfValuecache::singleton()->get("mfObjectmodel-Address-".$this->billingaddress_id); - if($this->billingaddress === null) { - $this->billingaddress = new Address($this->billingaddress_id); - if($this->billingaddress->id) { - mfValuecache::singleton()->set("mfObjectmodel-Address-".$this->billingaddress_id, $this->billingaddress); - } - } - return $this->billingaddress; + + if(!$this->id) { + return null; } + if($name == "product") { $this->product = mfValuecache::singleton()->get("mfObjectmodel-Product-".$this->product_id); if($this->product === null) { @@ -61,6 +160,69 @@ class Contract extends mfBaseModel { return $this->orderproduct; } + if($name == "contractConfigGroups") { + $product = $this->getProperty("product"); + $this->contractConfigGroups = ContractconfigGroupModel::search(['producttech_id' => $product->producttech_id]); + return $this->contractConfigGroups; + } + + if($name == "configgroups") { + $product = $this->getProperty("product"); + $this->configgroups = []; + foreach(ContractconfiggroupProductgroupModel::search(['productgroup_id' => $product->productgroup_id]) as $ccpg) { + $ccpg->contractconfiggroup->setContractId($this->id); + $this->configgroups[] = $ccpg->contractconfiggroup; + } + return $this->configgroups; + } + + if($name == "contractConfigItems") { + $product = $this->getProperty("product"); + + $this->contractConfigItems = []; + foreach(ProducttechAttributeModel::search(['producttech_id' => $product->producttech_id, "forcontract" => 1]) as $item) { + $item->setContractId($this->id); + $this->contractConfigItems [] = $item; + } + + return $this->contractConfigItems; + } + + if($name == "links") { + $this->links = ContractLinkModel::includesContractId($this->id, ["type" => $link]); + //var_dump($this->links);exit; + return $this->links; + } + + if(in_array($name, ['linkFrom','linkTo','upgradeFrom','upgradeTo','downgradeFrom','downgradeTo','productchangeFrom','productchangeTo','relocationFrom','relocationTo'])) { + if($this->$name === null) { + $this->getLinks(); + } + return $this->$name; + } + + if($name == "finisher") { + $this->finisher = mfValuecache::singleton()->get("Worker-id-".$this->finish_date_by); + if($this->finisher === null) { + $this->finisher = new User($this->finish_date_by); + if($this->finisher->id) { + mfValuecache::singleton()->set("Worker-id-".$this->finish_date_by, $this->finisher); + } + } + return $this->finisher; + } + + if($name == "canceler") { + $this->canceler = mfValuecache::singleton()->get("Worker-id-".$this->cancel_date_by); + if($this->canceler === null) { + $this->canceler = new User($this->cancel_date_by); + if($this->canceler->id) { + mfValuecache::singleton()->set("Worker-id-".$this->cancel_date_by, $this->canceler); + } + } + return $this->canceler; + } + if($name == "creator") { $this->creator = mfValuecache::singleton()->get("Worker-id-".$this->create_by); if($this->creator === null) { @@ -103,4 +265,45 @@ class Contract extends mfBaseModel { return $this->$name; } + + + /* + * When object is cloned, new object will call this funtion to let us clean up the new Contract. + * Throws Exception if cloning fails. + */ + public function __clone() { + $me = new User; + $me->loadMe(); + + $old_id = $this->id; + $old_nummer = $this->nummer; + unset($this->id); + + + // cleanup Contract daten + $this->orderproduct_id = null; + $this->order_date = null; + $this->finish_date = null; + $this->finish_date_by = null; + $this->cancel_date = null; + $this->cancel_date_by = null; + $this->create_by = $me->id; + $this->edit_by = $me->id; + + $this->create = null; + $this->edit = null; + $this->saved = 0; + $this->mode = "new"; + $this->_old_data = new StdClass(); + + //$this->save(); + + if($old_id == $this->id) { + $this->log->error("save() of cloned Contract $old_nummer failed!"); + throw new Exception("Saving clone failed."); + } + + $this->log->debug("Cloned Contract $old_id"); + } + } \ No newline at end of file diff --git a/application/Contract/ContractController.php b/application/Contract/ContractController.php index 2069beb4c..96ed5ae69 100644 --- a/application/Contract/ContractController.php +++ b/application/Contract/ContractController.php @@ -47,6 +47,14 @@ class ContractController extends mfBaseController { private function getPreparedFilter($filter) { $new_filter = []; + if(array_key_exists("show_canceled", $filter)) { + if($filter['show_canceled'] == 0) { + $new_filter['add-where'] = " AND (cancel_date IS NULL OR cancel_date > UNIX_TIMESTAMP())"; + } + } else { + $new_filter['add-where'] = " AND (cancel_date IS NULL OR cancel_date > UNIX_TIMESTAMP())"; + } + if(is_array($filter) && count($filter)) { foreach($filter as $name => $value) { $new_filter[$name] = $value; @@ -56,12 +64,13 @@ class ContractController extends mfBaseController { return $new_filter; } - protected function addAction() { - $this->layout()->setTemplate("Contract/Form"); - } - - protected function editAction() { - $id = $this->request->id; + protected function viewAction() { + $this->layout()->setTemplate("Contract/View"); + + $id = $this->request->contract_id; + if(!$id) { + $id = $this->request->id; + } if(!is_numeric($id) || !$id) { $this->layout()->setFlash("Vertrag nicht gefunden", "error"); $this->redirect("Contract"); @@ -75,11 +84,437 @@ class ContractController extends mfBaseController { $this->layout()->set("contract", $contract); + if($this->request->filter) { + $this->layout()->set("filter", $this->request->filter); + } + if($this->request->s) { + $this->layout()->set("filter", $this->request->s); + } + + } + + protected function productchangeAction() { + $this->layout()->setTemplate("Contract/ProductchangeForm"); + + $id = $this->request->contract_id; + if(!$id) { + $id = $this->request->id; + } + if(!is_numeric($id) || !$id) { + $this->layout()->setFlash("Vertrag nicht gefunden", "error"); + $this->redirect("Contract"); + } + + $contract = new Contract($id); + if(!$contract->id) { + $this->layout()->setFlash("Vertrag nicht gefunden", "error"); + $this->redirect("Contract"); + } + + $this->layout()->set("contract", $contract); + $this->layout()->set("terminations", TerminationModel::getAll()); + + if($this->request->filter) { + $this->layout()->set("filter", $this->request->filter); + } + if($this->request->s) { + $this->layout()->set("filter", $this->request->s); + } + } + + protected function saveProductchangeAction() { + $r = $this->request; + + $id = $r->contract_id; + if(!is_numeric($id) || !$id) { + $this->layout()->setFlash("Vertrag nicht gefunden", "error"); + $this->redirect("Contract"); + } + + $contract = new Contract($id); + if(!$contract->id) { + $this->layout()->setFlash("Vertrag nicht gefunden", "error"); + $this->redirect("Contract"); + } + + $new_contract = clone($contract); + + + $contract_data = []; + $contract_data['product_id'] = $r->product_id; + $contract_data['product_name'] = trim($r->product_name); + $contract_data['product_info'] = trim($r->product_info); + $contract_data['matchcode'] = trim($r->matchcode); + $contract_data['termination_id'] = $r->termination_id; + $contract_data['amount'] = 1; + $contract_data['price'] = $r->price; + $contract_data['price_setup'] = $r->price_setup; + $contract_data['price_nne'] = $r->price_nne; + $contract_data['price_nbe'] = $r->price_nbe; + $contract_data['note'] = trim($r->note); + + /* + * termination check + */ + $product = new Product($r->product_id); + if(!$product->id) { + $this->layout()->setFlash("Produkt nicht gefunden", "error"); + $this->redirect("Contract", "productchange", ["contract_id" => $id]); + } + + $contract_data['product_external'] = $product->external; + $contract_data['product_external_id'] = $product->external_id; + $contract_data['sla_id'] = $product->sla_id; + + $require_term = false; + if(array_key_exists(TT_ATTRIB_TERMINATION_REQUIRED_NAME, $product->attributes) && $product->attributes[TT_ATTRIB_TERMINATION_REQUIRED_NAME]->value == 1) { + //var_dump($prod->attributes); + $require_term = true; + $termination = new Termination($contract_data['termination_id']); + + if(!$contract_data['termination_id'] || !$termination->id) { + $this->layout()->setFlash("Produkt erfordert Anschluss.", "error"); + $this->redirect("Contract", "productchange", ["contract_id" => $id]); + } + } else { + $contract_data['termination_id'] = null; + } + + + $new_contract->update($contract_data); + $new_contract_id = $new_contract->save(); + + if(!$new_contract_id) { + $this->layout()->setFlash("Neuer Contract konnte nicht gespeichert werden", "error"); + $this->redirect("Contract", "productchange", ["contract_id" => $id]); + } + + + + if(is_array($r->links) && count($r->links)) { + foreach($r->links as $link_id => $action) { + $old_link = new ContractLink($link_id); + if(!$old_link->id) continue; + $new_link_origin_id = 0; + $new_link_origin_id = 0; + // check if link contains this contract + if($old_link->contract_id == $contract->id) { + $new_link_contract_id = $new_contract->id; + $new_link_origin_id = $old_link->origin_contract_id; + } elseif($old_link->origin_contract_id == $contract->id) { + $new_link_contract_id = $old_link->contract_id; + $new_link_origin_id = $new_contract->id; + } else { + continue; + } + + $new_link = ContractLinkModel::create([ + 'contract_id' => $new_link_contract_id, + 'origin_contract_id' => $new_link_origin_id, + 'type' => $old_link->type, + ]); + if(!$new_link->save()) { + $this->layout()->setFlash("Konnte neuen Link nicht speichern", "warn"); + } + + if($action == "cancel") { + $old_link->change_action = "cancel"; + if(!$old_link->save()) { + $this->layout()->setFlash("Konnte alten Link nicht speichern", "warn"); + } + } + + //var_dump($new_link);exit; + } + } + + /* + * Upgrade Link erstellen + */ + $change_type = "upgrade"; + /*if($contract->product_id != $new_contract->product_id) { + $change_type = "upgrade"; + } elseif($contract->matchcode != $new_contract->matchcode) { + $change_type = "relocation"; + } else { + $change_type = "productchange"; + }*/ + + $link = ContractLinkModel::create([ + 'contract_id' => $new_contract_id, + 'origin_contract_id' => $id, + 'type' => $change_type + ]); + + $link_id = $link->save(); + if(!$link_id) { + $this->layout()->setFlash("Konnte Verknüpfung nicht speichern", "warn"); + } + + $this->layout()->setFlash("Neuer Contract erfolgreich erstellt", "success"); + $this->redirect("Contract", "view", ["contract_id" => $new_contract_id]); + + + + } + + protected function finishContractAction() { + $r = $this->request; + + $id = $r->contract_id; + if(!is_numeric($id) || !$id) { + $this->layout()->setFlash("Contract nicht gefunden", "error"); + $this->redirect("Contract"); + } + + $contract = new Contract($id); + if(!$contract->id) { + $this->layout()->setFlash("Contract nicht gefunden", "error"); + $this->redirect("Contract"); + } + + $now = date('U'); + + /* + * Vorgänger Contracts kündigen + */ + foreach(ContractLinkModel::search(['contract_id' => $id]) as $link) { + if(!in_array($link->type, ["upgrade","downgrade","relocation","productchange"])) { + continue; + } + + $origin = $link->origin; + $origin->cancel_date = $now; + $origin->cancel_date_by = $this->me->id; + $origin->edit_by = $this->me->id; + if(!$origin->save()) { + $this->layout()->setFlash("Achtung: Konnte nicht alle Vorgängercontracts kündigen!", "warn"); + } + + /* + * alte Links übernehmen / kündigen + */ + foreach(ContractLinkModel::search(['type' => "link", 'contract_id' => $origin->id] ) as $old_link) { + // verlinkten Contract kündigen (wenn nicht schon gekündigt) + if($old_link->change_action == "cancel" && !$old_link->contract->cancel_date) { + $old_link->origin->update([ + 'cancel_date' => $now, + 'cancel_date_by' => $this->me->id, + 'edit_by' => $this->me->id + ]); + $old_link->origin->save(); + + $old_link->change_action = null; + $old_link->save(); + } + } + + foreach(ContractLinkModel::search(['type' => "link", 'origin_contract_id' => $origin->id] ) as $old_link) { + // verlinkten Contract kündigen (wenn nicht schon gekündigt) + if($old_link->change_action == "cancel" && !$old_link->contract->cancel_date) { + $old_link->contract->update([ + 'cancel_date' => $now, + 'cancel_date_by' => $this->me->id, + 'edit_by' => $this->me->id + ]); + $old_link->contract->save(); + + $old_link->change_action = null; + $old_link->save(); + } + } + + } + + + + $contract->finish_date = $now; + $contract->finish_date_by = $this->me->id; + if(!$contract->save()) { + $this->layout()->setFlash("Contract konnte nicht gespeichert werden", "error"); + $this->redirect("Contract", "view", ['contract_id' => $id]); + } + + /* + * bestehende Links übernehmen oder kündigen + */ + + $this->layout()->setFlash("Contract erfolgreich fertiggestellt", "success"); + $this->redirect("Contract", "view", ['contract_id' => $id]); + + } + + protected function addAction() { + $this->layout()->setTemplate("Contract/Form"); + $this->layout()->set("terminations", TerminationModel::getAll()); + + if($this->request->origin_contract_id) { + $origin = new Contract($this->request->origin_contract_id); + if($origin->id) { + $contract = new Contract(); + $contract->owner_id = $origin->owner_id; + $contract->billingaddress_id = $origin->billingaddress_id; + $contract->matchcode = $origin->matchcode; + //var_dump($contract);exit; + $this->layout()->set("contract", $contract); + $this->layout()->set("origin_contract_id", $origin->id); + } + } + } + + protected function editAction() { + $id = $this->request->contract_id; + if(!$id) { + $id = $this->request->id; + } + if(!is_numeric($id) || !$id) { + $this->layout()->setFlash("Vertrag nicht gefunden", "error"); + $this->redirect("Contract"); + } + + $contract = new Contract($id); + if(!$contract->id) { + $this->layout()->setFlash("Vertrag nicht gefunden", "error"); + $this->redirect("Contract"); + } + + $this->layout()->set("contract", $contract); + + if($this->request->f == "view") $this->layout()->set("f", "view"); + if($this->request->f != "view") $this->layout()->set("f", "index"); + + if($this->request->filter) { + $this->layout()->set("filter", $this->request->filter); + } + if($this->request->s) { + $this->layout()->set("filter", $this->request->s); + } + return $this->addAction(); } - - + protected function saveAction() { + $r = $this->request; + //var_dump($r); + + /* + * add or edit + */ + $id = $r->id; + if(is_numeric($id) && $id > 0) { + $mode = "edit"; + $contract = new Contract($id); + if(!$contract->id) { + $this->layout()->setFlash("Vertrag nicht gefunden", "error"); + $this->redirect("Contract"); + } + } else { + $id = false; + $mode = "add"; + } + + //var_dump($r->get());exit; + $contract_data = []; + $contract_data["owner_id"] = (int)$r->owner_id; + $contract_data["billingaddress_id"] = ($r->billingaddress_id) ? (int)$r->billingaddress_id : null; + $contract_data["product_id"] = (int)$r->product_id; + $contract_data["matchcode"] = $r->matchcode; + $contract_data["product_name"] = $r->product_name; + $contract_data["product_info"] = $r->product_info; + $contract_data['amount'] = ($r->amount) ? (float)$r->amount : 1; + $contract_data['price'] = (float)$r->price; + $contract_data['price_setup'] = (float)$r->price_setup; + $contract_data['price_nne'] = (float)$r->price_nne; + $contract_data['price_nbe'] = (float)$r->price_nbe; + $contract_data['billing_period'] = (int)$r->billing_period; + $contract_data['billing_delay'] = (int)$r->billing_delay; + $contract_data['finish_date'] = ($r->finish_date) ? $this->dateToTimestamp($r->finish_date) : null; + $contract_data['cancel_date'] = ($r->cancel_date) ? $this->dateToTimestamp($r->cancel_date) : null; + $contract_data['note'] = $r->note; + + + //var_dump($contract_data);exit; + + if($mode == "add") { + $contract = ContractModel::create($contract_data); + } else { + $contract->update($contract_data); + } + + $this->layout()->set("contract", $contract); + + if(!$contract_data["owner_id"]) { + $this->layout()->setFlash("Bitte Vertragsinhaber auswählen.", "error"); + return $this->addAction(); + } + if(!$contract_data["product_id"]) { + $this->layout()->setFlash("Bitte Produkt auswählen.", "error"); + return $this->addAction(); + } + if(!$contract_data['billing_period']) { + $this->layout()->setFlash("Bitte Rechnungsperiode auswählen.", "error"); + return $this->addAction(); + } + + if(!$contract->product_name) { + $product = new Product($contract_data["product_id"]); + if(!$product->id) { + $this->layout()->setFlash("Ungültiges Produkt.", "error"); + return $this->addAction(); + } + $contract->product_name = $product->name; + } + + //var_dump($contract);exit; + + $contract_id = $contract->save(); + if(!$contract_id) { + $this->layout()->setFlash("Fehler beim Speichern.", "error"); + $this->layout()->set("contract", $contract); + return $this->addAction(); + } + + $this->layout()->setFlash("Vertrag erfolgreich gespeichert.", "success"); + + /* + * Create link to origin contract if set + */ + if($mode == "add" && $r->origin_contract_id) { + $origin = new Contract($r->origin_contract_id); + if($origin->id) { + $link = ContractLinkModel::create([ + 'contract_id' => $contract_id, + 'origin_contract_id' => $origin->id, + 'type' => 'link' + ]); + $link->save(); + } + } + + + /* ContractLinks */ + + + $query = []; + if($r->s) { + $query['s'] = $r->s; + } + if($r->filter) { + $query["filter"] = $r->filter; + } + if($r->return != "index") { + $query['id'] = $contract_id; + } + + $qs = http_build_query($query); + + if($mode == "add" || $r->f == "view") { + $this->redirect("Contract", "view", $qs, "contract=$contract_id"); + } else { + $this->redirect("Contract", "Index", $qs); + } + + } protected function apiAction() { if(!$this->me->is(["Admin"])) { diff --git a/application/Contract/ContractModel.php b/application/Contract/ContractModel.php index d05f95155..67fabb5f9 100644 --- a/application/Contract/ContractModel.php +++ b/application/Contract/ContractModel.php @@ -1,20 +1,29 @@ select("Contract", "*", "1 = 1 ORDER BY owner_id,product_id,`create`"); + $res = $db->select("Contract", "*", "1 = 1 ORDER BY owner_id,`create`"); if($db->num_rows($res)) { while($data = $db->fetch_object($res)) { $items[] = new Contract($data); @@ -120,7 +129,7 @@ class ContractModel { LEFT JOIN Product ON (Contract.product_id = Product.id) WHERE $where GROUP BY Contract.id - ORDER BY Contract.owner_id,Contract.product_id,Contract.`create`"; + ORDER BY Contract.owner_id,Contract.`create`"; if(is_array($limit) && count($limit)) { if(is_numeric($limit['start']) && is_numeric($limit['count'])) { @@ -163,6 +172,13 @@ class ContractModel { } } + if(array_key_exists("billingaddress_id", $filter)) { + $billingaddress_id = $filter['billingaddress_id']; + if(is_numeric($billingaddress_id)) { + $where .= " AND Contract.billingaddress_id=$billingaddress_id"; + } + } + if(array_key_exists("product_id", $filter)) { $product_id = $filter['product_id']; if(is_numeric($product_id)) { @@ -192,6 +208,13 @@ class ContractModel { } } + if(array_key_exists("customer_number", $filter)) { + $customer_number = $filter['customer_number']; + if(is_numeric($customer_number)) { + $where .= " AND Address.customer_number=$customer_number"; + } + } + if(array_key_exists("owner", $filter)) { $owner = FronkDB::singleton()->escape($filter["owner"]); if($owner) { @@ -199,6 +222,10 @@ class ContractModel { } } + if(array_key_exists("add-where", $filter)) { + $where .= " ".$filter['add-where']; + } + //var_dump($filter, $where);exit; return $where; diff --git a/application/ContractLink/ContractLink.php b/application/ContractLink/ContractLink.php new file mode 100644 index 000000000..c62243391 --- /dev/null +++ b/application/ContractLink/ContractLink.php @@ -0,0 +1,69 @@ +$name == null) { + + if(!$this->id) { + return null; + } + + if($name == "origin") { + $this->origin = mfValuecache::singleton()->get("mfObjectmodel-Contract-".$this->origin_contract_id); + if($this->origin === null) { + $this->origin = new Contract($this->origin_contract_id); + if($this->origin->id) { + mfValuecache::singleton()->set("mfObjectmodel-Contract-".$this->id, $this->origin); + } + } + return $this->origin; + } + + if($name == "creator") { + $this->creator = mfValuecache::singleton()->get("Worker-id-".$this->create_by); + if($this->creator === null) { + $this->creator = new User($this->create_by); + if($this->creator->id) { + mfValuecache::singleton()->set("Worker-id-".$this->create_by, $this->creator); + } + } + return $this->creator; + } + + if($name == "editor") { + $this->editor = mfValuecache::singleton()->get("Worker-id-".$this->edit_by); + if($this->editor === null) { + $this->editor = new User($this->edit_by); + if($this->editor->id) { + mfValuecache::singleton()->set("Worker-id-".$this->edit_by, $this->editor); + } + } + return $this->editor; + } + + + + $classname = ucfirst($name); + $idfield = $name."_id"; + $this->$name = mfValuecache::singleton()->get("mfObjectmodel-$name-".$this->$idfield); + if(!$this->$name) { + $this->$name = new $classname($this->$idfield); + } + + + + if($this->$name->id) { + mfValuecache::singleton()->set("mfObjectmodel-$name-".$this->$name->id, $this->$name); + return $this->$name; + } else { + return null; + } + + } + + return $this->$name; + } +} \ No newline at end of file diff --git a/application/ContractLink/ContractLinkModel.php b/application/ContractLink/ContractLinkModel.php new file mode 100644 index 000000000..a3a7cfc30 --- /dev/null +++ b/application/ContractLink/ContractLinkModel.php @@ -0,0 +1,171 @@ + $value) { + if(property_exists(get_called_class(), $field)) { + $model ->$field = $value; + } + } + + $me = new User(); + $me->loadMe(); + + if($model->create_by === null) { + $model->create_by = $me->id; + } + if($model->edit_by === null) { + $model->edit_by = $me->id; + } + + return $model; + } + + public static function getAll() { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("ContractLink", "*", "1 = 1 ORDER BY contract_id,origin_contract_id"); + if($db->num_rows($res)) { + while($data = $db->fetch_object($res)) { + $items[] = new ContractLink($data); + } + } + return $items; + + } + + public static function getFirst($filter) { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $sql = "SELECT * FROM ContractLink + WHERE $where + ORDER BY contract_id,origin_contract_id + LIMIT 1"; + //var_dump($sql);exit; + $res = $db->query($sql); + if($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new ContractLink($data); + if($item->id) { + return $item; + } else { + return null; + } + } + return null; + } + + public static function includesContractId($contract_id, $filter=[]) { + $items = []; + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $sql = "SELECT * FROM ContractLink + WHERE (contract_id=$contract_id OR origin_contract_id=$contract_id) + AND $where + ORDER BY contract_id,origin_contract_id"; + + + mfLoghandler::singleton()->debug($sql); + + $res = $db->query($sql); + if($db->num_rows($res)) { + while($data = $db->fetch_object($res)) { + $items[$data->id] = new ContractLink($data); + } + } + + return $items; + } + + public static function count($filter) { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $sql = "SELECT COUNT(*) FROM ContractLink + WHERE $where + "; + + $res = $db->query($sql); + if($db->num_rows($res)) { + $data = $db->fetch_object($res); + return $data->cnt; + } + return 0; + } + + public static function search($filter, $limit = false) { + //var_dump($filter);exit; + $items = []; + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $sql = "SELECT * FROM ContractLink + WHERE $where + ORDER BY contract_id,origin_contract_id"; + + if(is_array($limit) && count($limit)) { + if(is_numeric($limit['start']) && is_numeric($limit['count'])) { + $sql .= " LIMIT ".$limit['start'].", ".$limit['count']; + } elseif(is_numeric($count)) { + $sql .= " LIMIT ".$limit['count']; + } + } + + mfLoghandler::singleton()->debug($sql); + + $res = $db->query($sql); + if($db->num_rows($res)) { + while($data = $db->fetch_object($res)) { + $items[$data->id] = new ContractLink($data); + } + } + + return $items; + } + + private static function getSqlFilter($filter) { + $where = "1=1 "; + + $db = FronkDB::singleton(); + + //var_dump($filter);exit; + + if(array_key_exists("contract_id", $filter)) { + $contract_id = $filter['contract_id']; + if(is_numeric($contract_id)) { + $where .= " AND ContractLink.contract_id = '$contract_id'"; + } + } + + if(array_key_exists("origin_contract_id", $filter)) { + $origin_contract_id = $filter['origin_contract_id']; + if(is_numeric($origin_contract_id)) { + $where .= " AND ContractLink.origin_contract_id = '$origin_contract_id'"; + } + } + + + + + //var_dump($filter, $where);exit; + return $where; + } + +} \ No newline at end of file diff --git a/application/Contractconfig/ContractconfigController.php b/application/Contractconfig/ContractconfigController.php index 2a2178342..be688787c 100644 --- a/application/Contractconfig/ContractconfigController.php +++ b/application/Contractconfig/ContractconfigController.php @@ -15,9 +15,82 @@ class ContractconfigController extends mfBaseController { } protected function indexAction() { - $groups = ContractconfigGroupModel::getAll(); - $this->layout()->set("groups", $groups); } + protected function viewAction() { + + } + + protected function editAction() { + $this->layout()->setTemplate("Contractconfig/Form"); + + $contract_id = $this->request->contract_id; + if(!$contract_id) { + $this->layout()->setFlash("Contract ID nicht gefunden.","error"); + $this->redirect("Contract"); + } + + $contract = new Contract($contract_id); + if(!$contract_id) { + $this->layout()->setFlash("Contract ID nicht gefunden.","error"); + $this->redirect("Contract"); + } + + if(!is_array($contract->configgroups) || !count($contract->configgroups)) { + $this->layout()->setFlash("Produkt hat keine Vertragsconfiggruppen hinterlegt.","info"); + $this->redirect("Contract", "View", ["id" => $contract_id]); + } + + $this->layout()->set("contract", $contract); + $this->layout()->set("groups", $contract->configgroups); + } + + protected function saveAction() { + $r = $this->request; + $contract_id = $r->contract_id; + + if(!is_numeric($contract_id) || $contract_id < 1) { + $this->layout()->setFlash("Contract ID nicht gefunden.","error"); + $this->redirect("Contract"); + } + + if(!is_array($r->itemvalues) || !count($r->itemvalues)) { + $this->layout()->setFlash("Keine Änderungen.","info"); + $this->redirect("Contract"); + } + + $error_items = []; + + foreach($r->itemvalues as $item_id => $itemvalue) { + $item = new ContractconfigItem($item_id); + if(!$item->id) { + $this->log->warn("Tried to save non-existant ContractconfigItem $item_id"); + continue; + } + $item->setContractId($contract_id); + if(!$item->value->set($itemvalue)) { + $error_items[$item->id] = $item->name; + continue; + } + if(!$item->value->save()) { + $this->layout()->set("request", $r); + $this->layout()->setFlash("Fehler beim Speichern von".$item->name,"info"); + return $this->editAction(); + } + } + + if(count($error_items)) { + $this->layout()->set("error_items", array_keys($error_items)); + $this->layout()->set("request", $r); + $this->layout()->setFlash("Konfiguration nicht vollständig gespeichert. Fehler in folgenden Feldern:\n
    ".implode(", ", $error_items), "warning"); + return $this->editAction(); + } + + $this->layout()->setFlash("Konfiguration gespeichert", "success"); + $this->redirect("Contract", "view", ['id' => $contract_id]); + + } + + } \ No newline at end of file diff --git a/application/ContractconfigGroup/ContractconfigGroup.php b/application/ContractconfigGroup/ContractconfigGroup.php deleted file mode 100644 index 66e425c03..000000000 --- a/application/ContractconfigGroup/ContractconfigGroup.php +++ /dev/null @@ -1,30 +0,0 @@ -$name == null) { - - if($name == "items") { - $this->items = ContractconfigItemModel::search(['group_id' => $this->id]); - return $this->items; - } - - $classname = ucfirst($name); - $idfield = $name."_id"; - $this->$name = new $classname($this->$idfield); - - if($this->$name->id) { - return $this->$name; - } else { - return null; - } - } - - return $this->$name; - } - -} \ No newline at end of file diff --git a/application/ContractconfigItem/ContractconfigItem.php b/application/ContractconfigItem/ContractconfigItem.php index e6fb43949..cae0ef27c 100644 --- a/application/ContractconfigItem/ContractconfigItem.php +++ b/application/ContractconfigItem/ContractconfigItem.php @@ -1,5 +1,77 @@ contract_id = $contract_id; + return true; + } + + public function getValue() { + $value = $this->getProperty("value"); + if(!$value) { + return null; + } + + if($this->type == "int") { + return $value->int; + } + if($this->type == "decimal") { + return $value->number; + } + + return $value->string; + } + + public function getTypedataArray() { + if(!$this->typedata) { + return []; + } + + return explode("\n", $this->typedata); + } + + public function getProperty($name) { + if($this->$name == null) { + + if(!$this->id) { + return null; + } + + if($name == "value") { + if(!$this->contract_id) { + return null; + } + $value = ContractconfigValueModel::getFirst(['item_id' => $this->id, "contract_id" => $this->contract_id]); + if(!$value) { + $me = new User(); + $me->loadMe(); + $value = new ContractconfigValue(); + $value->item_id = $this->id; + $value->contract_id = $this->contract_id; + $value->create_by = $me->id; + } + + $this->value = $value; + return $this->value; + } + + $classname = ucfirst($name); + $idfield = $name."_id"; + $this->$name = new $classname($this->$idfield); + + if($this->$name->id) { + return $this->$name; + } else { + return null; + } + } + + return $this->$name; + } } \ No newline at end of file diff --git a/application/ContractconfigItem/ContractconfigItemController.php b/application/ContractconfigItem/ContractconfigItemController.php new file mode 100644 index 000000000..2c14c0420 --- /dev/null +++ b/application/ContractconfigItem/ContractconfigItemController.php @@ -0,0 +1,82 @@ +needlogin=true; + $me = new User(); + $me->loadMe(); + $this->me = $me; + $this->layout()->set("me",$me); + + if(!$me->is(["Admin"])) { + $this->redirect("Dashboard"); + } + } + + protected function saveAction() { + $r = $this->request; + + $item_id = $r->item_id; + if(is_numeric($item_id) && $item_id > 0) { + $mode = "edit"; + $item = new ContractconfigItem($item_id); + if(!$item->id) { + $this->layout()->setFlash("Element nicht gefunden", "error"); + $this->redirect("Contractconfiggroup"); + } + } else { + $mode = "add"; + } + + $item_data['contractconfiggroup_id'] = $r->group_id; + $item_data['name'] = $r->name; + $item_data['displayname'] = $r->displayname; + $item_data['description'] = $r->description; + + $item_data['typedata'] = ""; + $item_data['pattern'] = ""; + + switch($r->type) { + case "string": + $item_data['type'] = "string"; + $item_data['pattern'] = $r->pattern; + break; + case "enum": + $item_data['type'] = "enum"; + $item_data['typedata'] = preg_replace(['/\n{2,}/','/^\n+/','/\n+$/'], ["\n",'',''], str_replace("\r","\n",$r->data)); + break; + case "int": + $item_data['type'] = "int"; + break; + case "decimal": + $item_data['type'] = "decimal"; + break; + default: + $this->layout()->setFlash("Ungültiger Datentyp!"); + $this->redirect("Contractconfiggroup"); + } + + if($mode == "edit") { + $item->update($item_data); + } else { + $item = ContractconfigItemModel::create($item_data); + } + + //var_dump($item);exit; + + $item_id = $item->save(); + + if(!$item_id) { + $this->layout()->setFlash("Fehler beim Speichern!"); + $this->redirect("Contractconfiggroup"); + } + + $this->layout()->setFlash("Element erfolgreich gespeichert", "success"); + $this->redirect("Contractconfiggroup"); + //$this->redirect("Contractconfig","Index","","item=$item_id"); + + + + } +} \ No newline at end of file diff --git a/application/ContractconfigItem/ContractconfigItemModel.php b/application/ContractconfigItem/ContractconfigItemModel.php index 7533d5929..045ad96c5 100644 --- a/application/ContractconfigItem/ContractconfigItemModel.php +++ b/application/ContractconfigItem/ContractconfigItemModel.php @@ -1,12 +1,14 @@ $value) { @@ -41,7 +43,7 @@ class ContractconfigItemModel { $db = FronkDB::singleton(); - $res = $db->select("ContractconfigItem", "*", "1=1 ORDER BY name, `create`"); + $res = $db->select("ContractconfigItem", "*", "1=1 ORDER BY `order`, name, `create`"); if($db->num_rows($res)) { while($data = $db->fetch_object($res)) { $items[] = new ContractconfigItem($data); @@ -55,7 +57,7 @@ class ContractconfigItemModel { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); - $res = $db->select("ContractconfigItem", "*", "$where LIMIT 1"); + $res = $db->select("ContractconfigItem", "*", "$where ORDER BY `order`,name LIMIT 1"); if($db->num_rows($res)) { $data = $db->fetch_object($res); $item = new ContractconfigItem($data); @@ -73,7 +75,7 @@ class ContractconfigItemModel { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); - $res = $db->select("ContractconfigItem", "*", "$where ORDER BY name"); + $res = $db->select("ContractconfigItem", "*", "$where ORDER BY `order`,name"); if($db->num_rows($res)) { while($data = $db->fetch_object($res)) { $items[] = new ContractconfigItem($data); @@ -100,6 +102,13 @@ class ContractconfigItemModel { } } + if(array_key_exists("contractconfiggroup_id", $filter)) { + $contractconfiggroup_id = $filter['contractconfiggroup_id']; + if(is_numeric($contractconfiggroup_id)) { + $where .= " AND contractconfiggroup_id=$contractconfiggroup_id"; + } + } + if(array_key_exists("group_id", $filter)) { $group_id = $filter['group_id']; if(is_numeric($group_id)) { diff --git a/application/ContractconfigValue/ContractconfigValue.php b/application/ContractconfigValue/ContractconfigValue.php index c59f79872..4e6c94e76 100644 --- a/application/ContractconfigValue/ContractconfigValue.php +++ b/application/ContractconfigValue/ContractconfigValue.php @@ -1,5 +1,63 @@ getProperty("item"); + + $me = new User(); + $me->loadMe(); + $this->edit_by = $me->id; + + if($new_value === null || strlen($new_value) == 0) { + $this->int = null; + $this->number = null; + $this->string = null; + return true; + } + + if($item->type == "int") { + if(!is_numeric($new_value)) return false; + $this->int = $new_value; + } elseif($item->type == "decimal") { + if(!is_float($new_value) && !is_numeric($new_value)) return false; + $this->number = $new_value; + } elseif(is_scalar($new_value)) { + $this->string = $new_value; + } else { + return false; + } + + return true; + } + + public function getProperty($name) { + if($this->$name == null) { + + if(!$this->id) { + return null; + } + + if($name == "item") { + $this->item = new ContractconfigItem($this->item_id); + if(!$this->item->id) { + return null; + } + return $this->item; + } + + $classname = ucfirst($name); + $idfield = $name."_id"; + $this->$name = new $classname($this->$idfield); + + if($this->$name->id) { + return $this->$name; + } else { + return null; + } + } + + return $this->$name; + } } \ No newline at end of file diff --git a/application/ContractconfigValue/ContractconfigValueModel.php b/application/ContractconfigValue/ContractconfigValueModel.php index f3e8441c2..cf8cec2f7 100644 --- a/application/ContractconfigValue/ContractconfigValueModel.php +++ b/application/ContractconfigValue/ContractconfigValueModel.php @@ -1,12 +1,11 @@ select("ContractconfigValue", "*", "$where LIMIT 1"); + $res = $db->select("ContractconfigValue", "*", "$where ORDER BY item_id, contract_id LIMIT 1"); if($db->num_rows($res)) { $data = $db->fetch_object($res); $item = new ContractconfigValue($data); @@ -73,7 +72,7 @@ class ContractconfigValueModel { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); - $res = $db->select("ContractconfigValue", "*", "$where ORDER BY name, filename"); + $res = $db->select("ContractconfigValue", "*", "$where ORDER BY item_id, contract_id"); if($db->num_rows($res)) { while($data = $db->fetch_object($res)) { $items[] = new ContractconfigValue($data); @@ -86,24 +85,44 @@ class ContractconfigValueModel { $where = "1=1 "; //var_dump($filter);exit; - if(array_key_exists("name", $filter)) { - $name = FronkDB::singleton()->escape($filter['name']); - if($name) { - $where .= " AND name='$name'"; + if(array_key_exists("contract_id", $filter)) { + $contract_id = $filter['contract_id']; + if(is_numeric($contract_id)) { + $where .= " AND contract_id=$contract_id"; + } elseif(is_array($contract_id) && count($contract_id)) { + $where .= " AND contract_id IN (". implode(",", $contract_id).")"; } } - if(array_key_exists("filename", $filter)) { - $filename = FronkDB::singleton()->escape($filter['filename']); - if($filename) { - $where .= " AND filename='$filename'"; + if(array_key_exists("item_id", $filter)) { + $item_id = $filter['item_id']; + if(is_numeric($item_id)) { + $where .= " AND item_id=$item_id"; + } elseif(is_array($item_id) && count($item_id)) { + $where .= " AND item_id IN (". implode(",", $item_id).")"; } } - if(array_key_exists("subfolder", $filter)) { - $subfolder = FronkDB::singleton()->escape($filter['subfolder']); - if($subfolder) { - $where .= " AND subfolder='$subfolder'"; + if(array_key_exists("int", $filter)) { + $int = $filter['int']; + if(is_numeric($int)) { + $where .= " AND int=$int"; + } elseif(is_array($int) && count($int)) { + $where .= " AND `int` IN (". implode(",", $int).")"; + } + } + + if(array_key_exists("string", $filter)) { + $string = FronkDB::singleton()->escape($filter['string']); + if($string) { + $where .= " AND `string`='$string'"; + } + } + + if(array_key_exists("text", $filter)) { + $text = FronkDB::singleton()->escape($filter['text']); + if($text) { + $where .= " AND `text`='$text'"; } } diff --git a/application/Contractconfiggroup/Contractconfiggroup.php b/application/Contractconfiggroup/Contractconfiggroup.php new file mode 100644 index 000000000..16d2f15c1 --- /dev/null +++ b/application/Contractconfiggroup/Contractconfiggroup.php @@ -0,0 +1,49 @@ +contract_id = $contract_id; + return true; + } + + public function getProperty($name) { + if($this->$name == null) { + + /*if($name == "items") { + $this->items = ContractconfigItemModel::search(['group_id' => $this->id]); + return $this->items; + }*/ + + if($name == "items") { + if($this->contract_id) { + foreach(ContractconfigItemModel::search(['contractconfiggroup_id' => $this->id]) as $item) { + $item->setContractId($this->contract_id); + $this->items[] = $item; + } + } else { + $this->items = ContractconfigItemModel::search(['contractconfiggroup_id' => $this->id]); + } + return $this->items; + } + + $classname = ucfirst($name); + $idfield = $name."_id"; + $this->$name = new $classname($this->$idfield); + + if($this->$name->id) { + return $this->$name; + } else { + return null; + } + } + + return $this->$name; + } + +} \ No newline at end of file diff --git a/application/Contractconfiggroup/ContractconfiggroupController.php b/application/Contractconfiggroup/ContractconfiggroupController.php new file mode 100644 index 000000000..a0dba06fd --- /dev/null +++ b/application/Contractconfiggroup/ContractconfiggroupController.php @@ -0,0 +1,50 @@ +needlogin=true; + $me = new User(); + $me->loadMe(); + $this->me = $me; + $this->layout()->set("me",$me); + + if(!$me->is(["Admin"])) { + $this->redirect("Dashboard"); + } + } + + protected function indexAction() { + $groups = ContractconfiggroupModel::search([]); + + $this->layout()->set("configgroups", $groups); + } + + + protected function saveAction() { + $groupname = ucfirst(trim($this->request->name)); + + if(!$groupname) { + $this->layout()->setFlash("Gruppenname darf nicht leer sein!", "error"); + $this->redirect("Contractconfiggroup"); + } + + $group = ContractconfiggroupModel::getFirst(["name" => $groupname]); + if($group) { + $this->layout()->setFlash("Gruppe gibs scho", "warn"); + $this->redirect("Contractconfiggroup"); + } + + $group = ContractconfiggroupModel::create(["name" => $groupname]); + $group_id = $group->save(); + if(!$group_id) { + $this->layout()->setFlash("Fehler beim Speichern", "error"); + $this->redirect("Contractconfiggroup"); + } + + $this->layout()->setFlash("Gruppe $groupname erfolgreich angelegt", "success"); + $this->redirect("Contractconfiggroup"); + } + + +} \ No newline at end of file diff --git a/application/ContractconfigGroup/ContractconfigGroupModel.php b/application/Contractconfiggroup/ContractconfiggroupModel.php similarity index 50% rename from application/ContractconfigGroup/ContractconfigGroupModel.php rename to application/Contractconfiggroup/ContractconfiggroupModel.php index 220b38ac3..46fcd78c8 100644 --- a/application/ContractconfigGroup/ContractconfigGroupModel.php +++ b/application/Contractconfiggroup/ContractconfiggroupModel.php @@ -1,12 +1,7 @@ $value) { if(property_exists(get_called_class(), $field)) { @@ -41,24 +36,24 @@ class ContractconfigGroupModel { $db = FronkDB::singleton(); - $res = $db->select("ContractconfigGroup", "*", "1=1 ORDER BY name, `create`"); + $res = $db->select("Contractconfiggroup", "*", "1=1 ORDER BY name, `create`"); if($db->num_rows($res)) { while($data = $db->fetch_object($res)) { - $items[] = new ContractconfigGroup($data); + $items[] = new Contractconfiggroup($data); } } return $items; } - public static function getFirst() { + public static function getFirst($filter = []) { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); - $res = $db->select("ContractconfigGroup", "*", "$where LIMIT 1"); + $res = $db->select("Contractconfiggroup", "*", "$where ORDER BY name, `create` LIMIT 1"); if($db->num_rows($res)) { $data = $db->fetch_object($res); - $item = new ContractconfigGroup($data); + $item = new Contractconfiggroup($data); if($item->id) { return $item; } else { @@ -73,10 +68,19 @@ class ContractconfigGroupModel { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); - $res = $db->select("ContractconfigGroup", "*", "$where ORDER BY name, filename"); + $sql = "SELECT Contractconfiggroup.* FROM Contractconfiggroup + LEFT JOIN ContractconfiggroupProductgroup ON (Contractconfiggroup.id = ContractconfiggroupProductgroup.contractconfiggroup_id) + LEFT JOIN Productgroup ON (ContractconfiggroupProductgroup.productgroup_id = Productgroup.id) + WHERE $where + GROUP BY Contractconfiggroup.id + ORDER BY Contractconfiggroup.name, Contractconfiggroup.`create` + "; + mfLoghandler::singleton()->debug($sql); + $res = $db->query($sql); + //$res = $db->select("Contractconfiggroup", "*", "$where ORDER BY name, `create`"); if($db->num_rows($res)) { while($data = $db->fetch_object($res)) { - $items[] = new ContractconfigGroup($data); + $items[] = new Contractconfiggroup($data); } } return $items; @@ -89,14 +93,25 @@ class ContractconfigGroupModel { if(array_key_exists("name", $filter)) { $name = FronkDB::singleton()->escape($filter['name']); if($name) { - $where .= " AND name='$name'"; + $where .= " AND Contractconfiggroup.name='$name'"; } } - if(array_key_exists("filename", $filter)) { - $filename = FronkDB::singleton()->escape($filter['filename']); - if($filename) { - $where .= " AND filename='$filename'"; + if(array_key_exists("producttech_id", $filter)) { + $producttech_id = $filter['producttech_id']; + if(is_numeric($producttech_id)) { + $where .= " AND producttech_id=$producttech_id"; + } elseif(is_array($producttech_id) && count($producttech_id)) { + $where .= " AND producttech_id IN (". implode(",", $producttech_id).")"; + } + } + + if(array_key_exists("productgroup_id", $filter)) { + $productgroup_id = $filter['productgroup_id']; + if(is_numeric($productgroup_id)) { + $where .= " AND productgroup_id=$productgroup_id"; + } elseif(is_array($productgroup_id) && count($productgroup_id)) { + $where .= " AND productgroup_id IN (". implode(",", $productgroup_id).")"; } } diff --git a/application/ContractconfiggroupProductgroup/ContractconfiggroupProductgroup.php b/application/ContractconfiggroupProductgroup/ContractconfiggroupProductgroup.php new file mode 100644 index 000000000..eb0f4a989 --- /dev/null +++ b/application/ContractconfiggroupProductgroup/ContractconfiggroupProductgroup.php @@ -0,0 +1,37 @@ +$name == null) { + + if(!$this->id) { + return null; + } + + if($name == "productgroup") { + $this->productgroup = new Productgroup($this->productgroup_id); + return $this->productgroup; + } + + if($name == "contractconfiggroup") { + $this->contractconfiggroup = new Contractconfiggroup($this->contractconfiggroup_id); + return $this->contractconfiggroup; + } + + $classname = ucfirst($name); + $idfield = $name."_id"; + $this->$name = new $classname($this->$idfield); + + if($this->$name->id) { + return $this->$name; + } else { + return null; + } + } + + return $this->$name; + } +} \ No newline at end of file diff --git a/application/ContractconfiggroupProductgroup/ContractconfiggroupProductgroupModel.php b/application/ContractconfiggroupProductgroup/ContractconfiggroupProductgroupModel.php new file mode 100644 index 000000000..30339e264 --- /dev/null +++ b/application/ContractconfiggroupProductgroup/ContractconfiggroupProductgroupModel.php @@ -0,0 +1,107 @@ + $value) { + if(property_exists(get_called_class(), $field)) { + $model ->$field = $value; + } + } + + $me = new User(); + $me->loadMe(); + + if($model->create_by === null) { + $model->create_by = $me->id; + } + if($model->edit_by === null) { + $model->edit_by = $me->id; + } + + return $model; + } + + public static function getAll() { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("ContractconfiggroupProductgroup", "*", "1=1"); + if($db->num_rows($res)) { + while($data = $db->fetch_object($res)) { + $items[] = new ContractconfiggroupProductgroup($data); + } + } + return $items; + + } + + public static function getFirst($filter) { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("ContractconfiggroupProductgroup", "*", "$where ORDER BY productgroup_id, contractconfiggroup_id LIMIT 1"); + if($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new ContractconfiggroupProductgroup($data); + if($item->id) { + return $item; + } else { + return null; + } + } + return null; + } + + public static function search($filter) { + $items = []; + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("ContractconfiggroupProductgroup", "*", "$where ORDER BY productgroup_id, contractconfiggroup_id"); + if($db->num_rows($res)) { + while($data = $db->fetch_object($res)) { + $items[] = new ContractconfiggroupProductgroup($data); + } + } + return $items; + } + + private static function getSqlFilter($filter) { + $where = "1=1 "; + + //var_dump($filter);exit; + if(array_key_exists("productgroup_id", $filter)) { + $productgroup_id = $filter['productgroup_id']; + if(is_numeric($productgroup_id)) { + $where .= " AND productgroup_id=$productgroup_id"; + } elseif(is_array($productgroup_id) && count($productgroup_id)) { + $where .= " AND productgroup_id IN (". implode(",", $productgroup_id).")"; + } + } + + if(array_key_exists("contractconfiggroup_id", $filter)) { + $contractconfiggroup_id = $filter['contractconfiggroup_id']; + if(is_numeric($contractconfiggroup_id)) { + $where .= " AND contractconfiggroup_id=$contractconfiggroup_id"; + } elseif(is_array($contractconfiggroup_id) && count($contractconfiggroup_id)) { + $where .= " AND contractconfiggroup_id IN (". implode(",", $contractconfiggroup_id).")"; + } + } + + //var_dump($filter, $where);exit; + return $where; + } + +} \ No newline at end of file diff --git a/application/Dashboard/DashboardController.php b/application/Dashboard/DashboardController.php index a71a17d88..da9f03ee7 100644 --- a/application/Dashboard/DashboardController.php +++ b/application/Dashboard/DashboardController.php @@ -18,15 +18,37 @@ class DashboardController extends mfBaseController { protected function testAction() { - $sql = "SELECT tt_preorder.* FROM `thetool_live`.Preorder tt_preorder - LEFT JOIN `thetool_addressdb`.view_hausnummer as adb_hausnummer ON (tt_preorder.adb_hausnummer_id = adb_hausnummer.hausnummer_id) - WHERE 1=1 AND deleted=0 AND preordercampaign_id=1 AND (adb_hausnummer.gemeinde like '%stift%' OR adb_hausnummer.plz like '%stift%' OR adb_hausnummer.strasse like '%stift%') - ORDER By lastname, firstname"; - $res = $this->db()->query($sql); - if($this->db()->num_rows($res)) { - $data = $this->db()->fetch_object($res); - var_dump($data);exit; + var_dump(ADBWohneinheitModel::count(["hausnummer_id" => 1772369])); + exit; + } + + protected function colorAction() { + + foreach(TT_CABLE_COLORS as $name => $color) { + if(!$color['two-color']) continue; + $hex = $color['hex']; + $hexfg = $color['hexfg']; + $hex2 = $color['hex2']; + $hexfg2 = $color['hexfg2']; + $r = $color['r']; + $g = $color['g']; + $b = $color['b']; + $r2 = $color['r2']; + $g2 = $color['g2']; + $b2 = $color['b2']; + + + $class = ".btn-outline-".$name." { + color: #$hexfg; + border-left-color: #$hex; + border-top-color: #$hex; + border-right-color: #$hex2; + border-bottom-color: #$hex2; + background: linear-gradient(90deg, rgba($r,$g,$b,.5) 0%, rgba($r,$g,$b,.5) 50%, rgba($r2,$g2,$b2,.5) 50%, rgba($r2,$g2,$b2,.5) 100%); +}"; + echo "
    $class
    \n"; } + exit; } protected function pdfAction() { @@ -72,8 +94,8 @@ class DashboardController extends mfBaseController { $email->setBody($body); $email->setFrom($from, $from_name); $email->setTo($to); - $email->setHeader("X-xinon-oid", $order->id); - $email->setHeader("X-xinon-pid", $product->id); + $email->setHeader("X-".MFAPPNAME."-oid", $order->id); + $email->setHeader("X-".MFAPPNAME."-pid", $product->id); $email->addAttachment($pdfpath, null, $pdfname, "application/pdf"); $email->send(); } diff --git a/application/Emailnotification/Emailnotification.php b/application/Emailnotification/Emailnotification.php index e3d12cb25..1fa645924 100644 --- a/application/Emailnotification/Emailnotification.php +++ b/application/Emailnotification/Emailnotification.php @@ -7,6 +7,7 @@ class Emailnotification { private $headers = []; private $subject; private $body; + private $html; private $from_name = false; private $email_from = false; private $email_to = false; @@ -14,7 +15,7 @@ class Emailnotification { public function __construct() { $this->headers = [ - 'X-Mailer' => 'XINON Mailer', + 'X-Mailer' => MFAPPNAME.' Mailer', ]; $this->email_from = TT_OUTGOING_EMAIL; @@ -52,6 +53,10 @@ class Emailnotification { $this->body = $body; } + public function setHtmlBody($html) { + $this->html = $html; + } + public function setFrom($email, $name = false) { $this->email_from = $email; $this->from_name = $name; @@ -65,7 +70,7 @@ class Emailnotification { if(!$this->email_to) { return false; } - if(!$this->body) { + if(!$this->body && !$this->html) { return false; } if(!is_array($this->headers) || !count($this->headers)) { @@ -75,14 +80,15 @@ class Emailnotification { return false; } - if(!$this->headers['Subject']) { + if(!array_key_exists("Subject", $this->headers) || !$this->headers['Subject']) { $this->setHeader("Subject", $this->subject); } - if(!$this->headers['From'] && $this->from_name) { + if((!array_key_exists("From", $this->headers) || !$this->headers['From']) && $this->from_name) { $this->headers['From'] = '"'.$this->from_name.'" <'.$this->email_from.'>'; } + $log = mfLoghandler::singleton(); //var_dump($this);exit; @@ -92,8 +98,13 @@ class Emailnotification { $mimeparams['head_charset']="utf-8"; $mime = new Mail_mime(); - $mime->setTXTBody($this->body); - + if($this->body) { + $mime->setTXTBody($this->body); + } + if($this->html) { + $mime->setHTMLBody($this->html); + } + //var_dump($this->attachments);exit; if(count($this->attachments)) { @@ -108,6 +119,7 @@ class Emailnotification { $body = $mime->get($mimeparams); $headers = $mime->headers($this->headers); + //$log->debug(print_r($headers, true)); $mail =& Mail::factory('mail', ["-f ".$this->email_from]); $mail->send($this->email_to, $headers, $body); diff --git a/application/File/File.php b/application/File/File.php index 1eac539d0..bf7d0be76 100644 --- a/application/File/File.php +++ b/application/File/File.php @@ -15,7 +15,11 @@ class File extends mfBaseModel { $id = $this->id; // delete file in store - $path = MFUPLOAD_FILE_SAVE_PATH."/documents/".$this->store_filename; + if($this->subfolder) { + $path = MFUPLOAD_FILE_SAVE_PATH."/".$this->subfolder."/".$this->store_filename; + } else { + $path = MFUPLOAD_FILE_SAVE_PATH."/".$this->store_filename; + } if(!unlink($path)) { $this->log->warn(__CLASS__."::delete(): Error unlinking file ($path)"); } diff --git a/application/File/FileModel.php b/application/File/FileModel.php index d3d709180..5be0f2eb3 100644 --- a/application/File/FileModel.php +++ b/application/File/FileModel.php @@ -7,6 +7,7 @@ class FileModel { public $store_filename; public $orig_filename; public $subfolder; + public $mimetype; public $create_by = null; public $edit_by = null; @@ -66,7 +67,7 @@ class FileModel { } - public static function getFirst() { + public static function getFirst($filter) { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); diff --git a/application/Network/NetworkController.php b/application/Network/NetworkController.php index 3d481889e..34e750194 100644 --- a/application/Network/NetworkController.php +++ b/application/Network/NetworkController.php @@ -100,6 +100,17 @@ class NetworkController extends mfBaseController { return $this->add(); } + $netaddress = NetworkAddressModel::getFirst(["network_id" => $new_id, "address_id" => $network->owner_id, "addresstype" => "netowner"]); + if(!$netaddress) { + $netaddress = NetworkAddressModel::create([ + 'network_id' => $new_id, + 'address_id' => $network->owner_id, + 'type' => "netowner" + ]); + //var_dump($netaddress);exit; + $netaddress->save(); + } + $this->layout()->setFlash("Netzgebiet erfolgreich gespeichert.", "success"); $this->redirect("Network", "Edit", ['id' => $new_id]); diff --git a/application/Network/NetworkModel.php b/application/Network/NetworkModel.php index 3db2692a9..ee5f47946 100644 --- a/application/Network/NetworkModel.php +++ b/application/Network/NetworkModel.php @@ -1,15 +1,16 @@ escape($filter['name']); + if($name) { + $where .= " AND Network.`name` = '$name'"; + } + } + + if(array_key_exists("name%", $filter)) { + $name = FronkDB::singleton()->escape($filter['name%']); + if($name) { + $where .= " AND Network.`name` LIKE '$name%'"; + } + } + if(array_key_exists("owner_id", $filter)) { - $ownerid= $filter['owner_id']; - if(is_numeric($ownerid)) { - $where .= " AND owner_id=$ownerid"; + $owner_id = $filter['owner_id']; + if(is_numeric($owner_id)) { + $where .= " AND owner_id=$owner_id"; + } elseif(is_array($owner_id) && count($owner_id)) { + $where .= " AND owner_id IN (". implode(",", $owner_id).")"; } } diff --git a/application/NetworkAddress/NetworkAddressModel.php b/application/NetworkAddress/NetworkAddressModel.php index cdd7d4e5b..6f0640717 100644 --- a/application/NetworkAddress/NetworkAddressModel.php +++ b/application/NetworkAddress/NetworkAddressModel.php @@ -66,7 +66,11 @@ class NetworkAddressModel { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); - $res = $db->select("NetworkAddress", "*", "$where ORDER BY `type`"); + $sql = "SELECT * FROM NetworkAddress WHERE $where ORDER BY `type`"; + mfLoghandler::singleton()->debug($sql); + $res = $db->query($sql); + + //$res = $db->select("NetworkAddress", "*", "$where ORDER BY `type`"); if($db->num_rows($res)) { $data = $db->fetch_object($res); $item = new NetworkAddress($data); @@ -84,7 +88,9 @@ class NetworkAddressModel { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); - $res = $db->select("NetworkAddress", "*", "$where ORDER BY `type`"); + $sql = "SELECT * FROM NetworkAddress WHERE $where ORDER BY `type`"; + $res = $db->query($sql); + //$res = $db->select("NetworkAddress", "*", "$where ORDER BY `type`"); if($db->num_rows($res)) { while($data = $db->fetch_object($res)) { $items[$data->id] = new NetworkAddress($data->id); @@ -112,23 +118,25 @@ class NetworkAddressModel { } } - if(is_array($filter['addresstype']) && count($filter['addresstype'])) { - $at = $filter['addresstype']; - $in = []; - foreach(TT_ROLES as $role) { - if(in_array($role, $at)) { - $role = $db->escape($role); - $in[] = "NetworkAddress.type = '$role'"; + if(array_key_exists("addresstype", $filter)) { + if(is_array($filter['addresstype'])) { + $addresstypes = []; + foreach(TT_ROLES as $role) { + if(in_array($role, $filter['addresstype'])) { + $addresstypes[] = $role; + } + } + $where .= " AND NetworkAddress.type IN ('".implode("', '", $addresstypes)."')"; + } else { + $addresstype = FronkDB::singleton()->escape($filter['addresstype']); + if(in_array($addresstype, TT_ROLES)) { + $where .= " AND NetworkAddress.type = '$addresstype'"; } } - - $or = ""; - if(count($in)) { - $or = implode(" OR ", $in); - $where .= " AND ( $or )"; - } } + + //var_dump($filter, $where);exit; return $where; } diff --git a/application/Order/Order.php b/application/Order/Order.php index f084cb28b..b493ab021 100644 --- a/application/Order/Order.php +++ b/application/Order/Order.php @@ -9,6 +9,7 @@ class Order extends mfBaseModel { private $contracts; private $terminations; private $journals; + private $install_products; private $files; private $creator; private $editor; @@ -92,6 +93,68 @@ class Order extends mfBaseModel { } } + public function sendSpinEmail() { + $owner = $this->getProperty("owner"); + + $spin_pdf_template = "Emailtemplates/attachments/new_order_spin.pdf"; + $new_order_template = "Emailtemplates/customer/new_order"; + + $pdf_vars = [ + 'order' => $this, + 'owner' => $owner + ]; + + + if(TT_CUSTOM_ORDER_PDF_PER_NETOWNER) { + $terms = $this->getTerminations(); + if(is_array($terms) && count($terms) && $terms[0]->id) { + $netowner = $terms[0]->building->network->owner; + } else { + $netowner = new Address(TT_CUSTOM_ORDER_PDF_DEFAULT_OWNER_ID); + } + $pdf_vars['netowner'] = $netowner; + } + + // render service pin PDF + $pdf = new PdfForm($spin_pdf_template, $pdf_vars); + $pdfpath = $pdf->render(); + $tvalue = $pdf->getReturnedValues(); + $pdfname = $tvalue['filename']; + + // send email to customer + // TODO template rendern auslagern nach Emailtempate klasse + $tpl = new Layout(); + $tpl->setTemplate($new_order_template); + + foreach($pdf_vars as $name => $val) { + $tpl->set($name, $val); + } + + $body = $tpl->render(); + $values = $tpl->getReturnedValue(); + + $subject = $values['subject']; + $from = $values['from_email']; + $from_name = $values['from_email_name']; + $to = $owner->email; + + if(!$subject || !$from || !$from_name || !$to) { + $this->log->warn("Service PIN Email not sent. (subject: '$subject', from: '$from', from_email: '$from_email', to: '$to')"); + } else { + $email = new Emailnotification(); + $email->setSubject($subject); + $email->setBody($body); + $email->setFrom($from, $from_name); + $email->setTo($to); + $email->setHeader("X-".MFAPPNAME."-Oid", $this->id); + $email->addAttachment($pdfpath, null, $pdfname, "application/pdf"); + $email->send(); + $this->log->info(__CLASS__."::sendSpinEmail(): Sending new SPIN for ".$owner->getCompanyOrName()." (".$owner->id.")"); + } + + return true; + } + public function sendIntBillinfoEmail() { // TODO template rendern auslagern nach Emailtempate klasse $tpl = new Layout(); @@ -118,7 +181,7 @@ class Order extends mfBaseModel { $email->setBody($body); $email->setFrom($from, $from_name); $email->setTo($to); - $email->setHeader("X-xinon-oid", $this->id); + $email->setHeader("X-".MFAPPNAME."-oid", $this->id); $email->send(); return true; @@ -157,7 +220,7 @@ class Order extends mfBaseModel { $email->setBody($body); $email->setFrom($from, $from_name); $email->setTo($to); - $email->setHeader("X-Xinon-Oid", $this->id); + $email->setHeader("X-".MFAPPNAME."-Oid", $this->id); $email->send(); return true; @@ -212,8 +275,8 @@ class Order extends mfBaseModel { $email->setBody($body); $email->setFrom($from, $from_name); $email->setTo($to); - $email->setHeader("X-Xinon-Oid", $this->id); - $email->setHeader("X-Xinon-OFid", $file->id); + $email->setHeader("X-".MFAPPNAME."-Oid", $this->id); + $email->setHeader("X-".MFAPPNAME."-OFid", $file->id); $email->addAttachment($filepath, null, $file->file->filename, $mimetype); $email->send(); $this->log->info(__CLASS__."::save(): Sending Order Fileupload Email to '$to'"); @@ -269,6 +332,21 @@ class Order extends mfBaseModel { return $this->products; } + if($name == "install_products") { + $this->install_products = []; + + foreach($this->getProperty("products") as $orderproduct) { + $product = $orderproduct->product; + //$atrribs = $product->attributes; + //var_dump($attribs);exit; + if(is_array($product->attributes) && array_key_exists("vot", $product->attributes) && $product->attributes["vot"] == 1) { + $this->install_products[] = $product; + } + } + //var_dump($this->install_products);exit; + return $this->install_products; + } + if($name == "customer_type") { $this->customer_type = "residential"; foreach($this->getProperty("products") as $order_product) { diff --git a/application/Order/OrderController.php b/application/Order/OrderController.php index 5ffa2c29a..d9b800bc3 100644 --- a/application/Order/OrderController.php +++ b/application/Order/OrderController.php @@ -67,9 +67,12 @@ class OrderController extends mfBaseController { } } - $filter = []; + $rfilter = $this->request->filter; + if(!$rfilter) { + $rfilter = []; + } - $this->layout->set("filter", $this->request->filter); + $this->layout->set("filter", $rfilter); $filter = $this->getPreparedFilter($this->request->filter); // pagination defaults @@ -792,14 +795,16 @@ class OrderController extends mfBaseController { } // add techcontact as AddressLink to owner if not exists - $link = AddressLinkModel::getFirst(['address_id' => $techcontact->id, 'origin_address_id' => $order->owner_id, 'type' => "techcontact"]); - if(!$link) { - $linkdata = []; - $linkdata['address_id'] = $techcontact->id; - $linkdata['origin_address_id'] = $order->owner_id; - $linkdata['type'] = "techcontact"; - $link = AddressLinkModel::create($linkdata); - $link->save(); + if($techcontact->id) { + $link = AddressLinkModel::getFirst(['address_id' => $techcontact->id, 'origin_address_id' => $order->owner_id, 'type' => "techcontact"]); + if(!$link) { + $linkdata = []; + $linkdata['address_id'] = $techcontact->id; + $linkdata['origin_address_id'] = $order->owner_id; + $linkdata['type'] = "techcontact"; + $link = AddressLinkModel::create($linkdata); + $link->save(); + } } @@ -868,6 +873,7 @@ class OrderController extends mfBaseController { continue; } $product_data['termination_id'] = $p['termination_id']; + $order_termination_id = $p['termination_id']; } else { $product_data['termination_id'] = null; } @@ -905,59 +911,28 @@ class OrderController extends mfBaseController { $owner->save(); } } - - // generate and send Service PIN - // only if owner_id wasn't changed - if(!$owner->spin && (!property_exists($order->_old_data, "owner_id") || $order->owner_id == $order->_old_data->owner_id)) { - $this->log->debug(__CLASS__."::save(): creating new SPIN for ".$owner->getCompanyOrName()." (".$owner->id.")"); - $spin = $owner->generateServicePin(); - if($spin && !AddressModel::search(['spin' => $spin])) { - $owner->spin = $spin; - if($owner->save()) { - - // render service pin PDF - $pdf = new PdfForm("Emailtemplates/attachments/new_order_spin.pdf", ["owner" => $owner, "order" => $order]); - $pdfpath = $pdf->render(); - $tvalue = $pdf->getReturnedValues(); - $pdfname = $tvalue['filename']; - - // send email to customer - // TODO template rendern auslagern nach Emailtempate klasse - $tpl = new Layout(); - $tpl->setTemplate("Emailtemplates/customer/new_order"); - $tpl->set("owner", $owner); - $body = $tpl->render(); - - $values = $tpl->getReturnedValue(); - - $subject = $values['subject']; - $from = $values['from_email']; - $from_name = $values['from_email_name']; - $to = $owner->email; - - if(!$subject || !$from || !$from_name || !$to) { - $this->log->warn("Service PIN Email not sent. (subject: '$subject', from: '$from', from_email: '$from_email', to: '$to')"); - } else { - $email = new Emailnotification(); - $email->setSubject($subject); - $email->setBody($body); - $email->setFrom($from, $from_name); - $email->setTo($to); - $email->setHeader("X-Xinon-Oid", $order->id); - $email->setHeader("X-Xinon-Pid", $product->id); - $email->addAttachment($pdfpath, null, $pdfname, "application/pdf"); - $email->send(); - $this->log->info(__CLASS__."::save(): Sending new SPIN for ".$owner->getCompanyOrName()." (".$owner->id.")"); - } - - } - - } - } else { - $this->log->debug(__CLASS__."::save(): NOT creating new SPIN for ".$owner->getCompanyOrName()." (".$owner->id."): SPIN exists or owner of Order was changed"); - } } } + + // generate and send Service PIN, only if: + // - owner does not have a Service PIN yet + // - there are no external products + // - owner_id was not set before or owner_id wasn't changed + + // TODO: move this to Order class + if(!$ext_products && !$owner->spin && (!property_exists($order->_old_data, "owner_id") || $order->owner_id == $order->_old_data->owner_id)) { + $this->log->debug(__CLASS__."::save(): creating new SPIN for ".$owner->getCompanyOrName()." (".$owner->id.")"); + $spin = $owner->generateServicePin(); + if($spin && !AddressModel::search(['spin' => $spin])) { + $owner->spin = $spin; + if($owner->save()) { + $order->sendSpinEmail(); + } + } + } else { + $this->log->debug(__CLASS__."::save(): NOT creating new SPIN for ".$owner->getCompanyOrName()." (".$owner->id."): SPIN exists or owner of Order was changed or external products"); + } + } //var_dump($_FILES['OrderFileUpload']);exit; @@ -1210,8 +1185,24 @@ class OrderController extends mfBaseController { $this->redirect("Order"); } + $pdf_vars = [ + 'order' => $order, + 'owner' => $owner + ]; + + + if(TT_CUSTOM_ORDER_PDF_PER_NETOWNER) { + $terms = $order->terminations; + if(is_array($terms) && count($terms) && $terms[0]->id) { + $netowner = $terms[0]->building->network->owner; + } else { + $netowner = new Address(TT_CUSTOM_ORDER_PDF_DEFAULT_OWNER_ID); + } + $pdf_vars['netowner'] = $netowner; + } + // render service pin PDF - $pdf = new PdfForm("Emailtemplates/attachments/new_order_spin.pdf", ["owner" => $owner, "order" => $order]); + $pdf = new PdfForm("Emailtemplates/attachments/new_order_spin.pdf", $pdf_vars); $pdfpath = $pdf->render(); $tvalue = $pdf->getReturnedValues(); $pdfname = $tvalue['filename']; @@ -1239,45 +1230,13 @@ class OrderController extends mfBaseController { $this->redirect("Order"); } - // render service pin PDF - $pdf = new PdfForm("Emailtemplates/attachments/new_order_spin.pdf", ["owner" => $owner, "order" => $order]); - $pdfpath = $pdf->render(); - $tvalue = $pdf->getReturnedValues(); - $pdfname = $tvalue['filename']; - - // TODO template rendern auslagern nach Emailtempate klasse - $tpl = new Layout(); - $tpl->setTemplate("Emailtemplates/customer/new_order"); - $tpl->set("owner", $owner); - $body = $tpl->render(); - - $values = $tpl->getReturnedValue(); - - //var_dump($values);exit; - - $subject = $values['subject']; - $from = $values['from_email']; - $from_name = $values['from_email_name']; - $to = $owner->email; - - if(!$subject || !$from || !$from_name || !$to) { - $this->log->warn("Service PIN Email not sent. (subject: '$subject', from: '$from', from_email: '$from_name', to: '$to')"); - $this->layout()->setFlash("Beim Email versenden ist ein Fehler aufgetreten.", "error"); - $this->redirect("Order"); - } else { - $email = new Emailnotification(); - $email->setSubject($subject); - $email->setBody($body); - $email->setFrom($from, $from_name); - $email->setTo($to); - $email->setHeader("X-Xinon-Oid", $order->id); - $email->setHeader("X-Xinon-Pid", $product->id); - $email->addAttachment($pdfpath, null, $pdfname, "application/pdf"); - $email->send(); - + if($order->sendSpinEmail()) { $this->layout()->setFlash("Service PIN wurde erfolgreich versendet.", "success"); - $this->redirect("Order"); + } else { + $this->layout()->setFlash("Fehler beim SPIN Versand!", "success"); } + + $this->redirect("Order"); } } diff --git a/application/Preorder/Preorder.php b/application/Preorder/Preorder.php index 28f0c6300..c511574f2 100644 --- a/application/Preorder/Preorder.php +++ b/application/Preorder/Preorder.php @@ -2,6 +2,7 @@ class Preorder extends mfBaseModel { protected $forcestr = ['street','company','zip','phone','email','note']; + private $status; private $campaign; private $partner; private $building; @@ -34,6 +35,94 @@ class Preorder extends mfBaseModel { return $ucode; } + public function getApiArray() { + if(!$this->id) { + return false; + } + + $hausnummer = $this->getProperty("adb_hausnummer"); + $wohneinheit = $this->getProperty("adb_wohneinheit"); + $campaign = $this->getProperty("campaign"); + + + $a = []; + $a['code'] = strtoupper($this->ucode); + $a['oaid'] = $this->oaid; + $a['status'] = $this->getProperty("status")->getApiArray(); + $a['connectionType'] = $this->connection_type; + $a['connectionCount'] = ($this->connection_count) ? (int)$this->connection_count : 1; + $a['isAdditionalOrder'] = ($this->is_additional_order) ? true : false; + $a['technology'] = ($this->technology) ? $this->technology : null; + $a['patchposition'] = ($this->patchposition) ? $this->patchposition : null; + $a['preorderType'] = $this->type; + $a['acceptMarketing'] = ($this->accept_marketing) ? true : false; + $a['acceptAgb'] = ($this->accept_agb) ? true : false; + $a['acceptDsgvo'] = ($this->accept_dsgvo) ? true : false; + $a['acceptWithdrawal'] = ($this->accept_withdrawal) ? true : false; + $a['address_info'] = ($this->address_info) ? $this->address_info : null; + + $address = []; + $address['cluster_id'] = $hausnummer->netzgebiet->extref; + $address['street'] = $hausnummer->strasse->name; + $address['housenumber'] = $hausnummer->hausnummer; + $address['zip'] = $hausnummer->plz->plz; + $address['city'] = $hausnummer->strasse->gemeinde->name; + $address['municipality'] = ""; + $address['district'] = $hausnummer->ortschaft->name; + $address['block'] = ($wohneinheit->block) ? $wohneinheit->block : null; + $address['stock'] = ($wohneinheit->stock) ? $wohneinheit->stock : null; + $address['stiege'] = ($wohneinheit->stiege) ? $wohneinheit->stiege : null; + $address['tuer'] = ($wohneinheit->tuer) ? $wohneinheit->tuer : null; + $address['unit_string'] = ($wohneinheit->bezeichner) ? $wohneinheit->bezeichner : null; + $address['is_shipping'] = ($this->shipping_address == "address") ? true : false; + + if($campaign->district_is_city) { + $address['city'] = $hausnummer->ortschaft->name; + $address['municipality'] = $hausnummer->strasse->gemeinde->name; + } else { + unset($address['municipality']); + } + + $customer = []; + $customer['company'] = ($this->company) ? $this->company : null; + $customer['uid'] = ($this->uid) ? $this->uid : null; + $customer['firstnam'] = ($this->firstname) ? $this->firstname : null; + $customer['lastname'] = ($this->lastname) ? $this->lastname : null; + $customer['street'] = ($this->street) ? $this->street : null; + $customer['housenumber'] = ($this->housenumber) ? $this->housenumber : null; + $customer['zip'] = ($this->zip) ? $this->zip : null; + $customer['city'] = ($this->city) ? $this->city : null; + $customer['block'] = ($this->block) ? $this->block : null; + $customer['stock'] = ($this->stock) ? $this->stock : null; + $customer['stiege'] = ($this->stiege) ? $this->stiege : null; + $customer['tuer'] = ($this->tuer) ? $this->tuer : null; + $customer['unit_string'] = ($this->unit_string) ? $this->unit_string : null; + $customer['phone'] = ($this->phone) ? $this->phone : null; + $customer['email'] = ($this->email) ? $this->email : null; + + $a['address'] = $address; + $a['customer'] = $customer; + + $a['addonServices'] = null; + if($this->addon_services) { + $addon_services = json_decode($this->addon_services); + if(json_last_error() === JSON_ERROR_NONE) { + $a['addonServices'] = $addon_services; + } + } + + $a['additionalData'] = null; + if($this->addon_data) { + $addon_data = json_decode($this->addon_data); + if(json_last_error() === JSON_ERROR_NONE) { + $a['additionalData'] = $addon_data; + } + } + + return $a; + } + + public function getProperty($name) { if($this->$name == null) { @@ -42,6 +131,17 @@ class Preorder extends mfBaseModel { return $this->campaign; } + if($name == "status") { + $this->status = mfValuecache::singleton()->get("mfObjectmodel-Preorderstatus-".$this->status_id); + if(!$this->status) { + $this->status = new Preorderstatus($this->status_id); + if($this->status->id) { + mfValuecache::singleton()->set("mfObjectmodel-Preorderstatus-".$this->status_id, $this->status); + } + } + return $this->status; + } + if($name == "partner") { $this->partner = mfValuecache::singleton()->get("mfObjectmodel-Address-".$this->partner_id); if(!$this->partner) { @@ -74,6 +174,9 @@ class Preorder extends mfBaseModel { return $this->adb_wohneinheit; } + if($name == "addon_services") { + + } if($name == "creator") { $user = mfValuecache::singleton()->get("Worker-id-".$this->create_by); diff --git a/application/Preorder/PreorderController.php b/application/Preorder/PreorderController.php index d21e67019..b7ea7249c 100644 --- a/application/Preorder/PreorderController.php +++ b/application/Preorder/PreorderController.php @@ -9,7 +9,7 @@ class PreorderController extends mfBaseController { $this->me = $me; $this->layout()->set("me",$me); - if(!$me->is(["Admin", "salespartner"])) { + if(!$me->is(["Admin", "netowner", "salespartner"])) { $this->redirect("Dashboard"); } } @@ -37,21 +37,49 @@ class PreorderController extends mfBaseController { $pagination['start'] = intval($this->request->s); } - $campaign_filter = []; + $preorder_filter = $filter; + $my_campaigns = []; + $my_campaign_ids = []; - if($filter['preordercampaign_id']) { - $campaign_id = $filter['preordercampaign_id']; - if(is_numeric($campaign_id) && $campaign_id > 0) { - $campaign = new Preordercampaign($campaign_id); - $this->layout()->set("campaign", $campaign); + if($this->me->is("Admin")) { + if($filter['preordercampaign_id']) { + $this->layout()->set("campaign", new Preordercampaign($filter['preordercampaign_id'])); + } else { + $my_campaigns = PreordercampaignModel::getAll(); + } + $this->layout()->set("my_campaigns", PreordercampaignModel::getAll()); + } else { + $my_networks = $this->me->myNetworks(["netowner", "salespartner"]); + //var_dump($my_networks);exit; + + foreach($my_networks as $network) { + foreach(PreordercampaignModel::search(['network_id' => $network->id]) as $campaign) { + $my_campaigns[] = $campaign; + if(!in_array($campaign->id, $my_campaign_ids)) $my_campaign_ids[] = $campaign->id; + } + } + //var_dump($my_network_ids,$my_campaign_ids);exit; + $this->layout()->set("my_campaigns", $my_campaigns); + + if($filter['preordercampaign_id'] && in_array($filter['preordercampaign_id'], $my_campaign_ids)) { + $campaign_id = $filter['preordercampaign_id']; + if(is_numeric($campaign_id) && $campaign_id > 0) { + $campaign = new Preordercampaign($campaign_id); + $this->layout()->set("campaign", $campaign); + } + } else { + $filter['preordercampaign_id'] = $my_campaign_ids; } } - //var_dump($filter);exit; - $pagination['maxItems'] = PreorderModel::count($filter); + if($filter['addon_services']) { + $pagination['maxItems'] = PreorderModel::countOrderedAddonservices($filter); + $preorders = PreorderModel::searchOrderedAddonservices($filter, $pagination); + } else { + $pagination['maxItems'] = PreorderModel::count($filter); + $preorders = PreorderModel::search($filter, $pagination); + } $this->layout()->set("pagination", $pagination); - - $preorders = PreorderModel::search($filter, $pagination); $this->layout()->set("preorders", $preorders); } @@ -75,12 +103,27 @@ class PreorderController extends mfBaseController { if(array_key_exists("address", $filter)) { $address = $this->db()->escape($filter['address']); - $new_filter['add-where'] = " AND (adb_hausnummer.gemeinde like '%$address%' OR adb_hausnummer.plz like '%$address%' OR adb_hausnummer.strasse like '%$address%')"; + $new_filter['add-where'] .= " AND (adb_hausnummer.gemeinde like '%$address%' OR adb_hausnummer.plz like '%$address%' OR adb_hausnummer.strasse like '%$address%')"; } if(array_key_exists("kunde", $filter)) { $kunde = $this->db()->escape($filter['kunde']); - $new_filter['add-where'] = " AND (firstname like '%$kunde%' OR lastname like '%$kunde%' OR street like '%$kunde%' OR zip like '%$kunde%' OR city like '%$kunde%')"; + $new_filter['add-where'] .= " AND (company like '%$kunde%' OR firstname like '%$kunde%' OR lastname like '%$kunde%' OR street like '%$kunde%' OR zip like '%$kunde%' OR city like '%$kunde%')"; + } + + + $new_filter['addon_services'] = false; + if(array_key_exists("addon_services", $filter) && $filter['addon_services'] == 1) { + $new_filter['addon_services'] = true; + } + + if(array_key_exists("address_source", $filter)) { + if($filter['address_source'] == "manual") { + $new_filter['address_created'] = true; + } + if($filter['address_source'] == "addressdb") { + $new_filter['address_created'] = null; + } } @@ -121,7 +164,7 @@ class PreorderController extends mfBaseController { //var_dump($products);exit; $this->layout()->set("products", $products); - $partners = AddressModel::search(['addresstype' => ['salespartner']]); + $partners = AddressModel::search(['addresstype' => ['netowner','salespartner']]); $this->layout()->set("partners", $partners); } @@ -149,7 +192,7 @@ class PreorderController extends mfBaseController { protected function saveAction() { $r = $this->request; - //var_dump($r); + //var_dump($r);exit; /* * add or edit @@ -232,28 +275,33 @@ class PreorderController extends mfBaseController { $data['accept_marketing'] = 1; } - $data['price'] = ($r->price) ? $r->price : 0; - $data['price_setup'] = ($r->price_setup) ? $r->price_setup : 0; - $data['price_nne'] = ($r->price_nne) ? $r->price_nne : 0; - $data['price_nbe'] = ($r->price_nbe) ? $r->price_nbe : 0; + $data['price'] = ($r->price) ? Layout::commaToDot($r->price) : 0; + $data['price_setup'] = ($r->price_setup) ? Layout::commaToDot($r->price_setup) : 0; + $data['price_nne'] = ($r->price_nne) ? Layout::commaToDot($r->price_nne) : 0; + $data['price_nbe'] = ($r->price_nbe) ? Layout::commaToDot($r->price_nbe) : 0; $data['billing_delay'] = ($r->billing_delay) ? $r->billing_delay : 0; - + //var_dump($r->partner_id);exit; if($r->partner_id) { $data['partner_id'] = $r->partner_id; } else { $data['partner_id'] = null; } - $data['company'] = $r->company; - $data['uid'] = $r->uid; - $data['firstname'] = $r->firstname; - $data['lastname'] = $r->lastname; - $data['street'] = $r->street; - $data['zip'] = $r->zip; - $data['city'] = $r->city; - $data['phone'] = $r->phone; - $data['email'] = $r->email; - $data['note'] = $r->note; + $data['company'] = (trim($r->company)) ? trim($r->company) : null; + $data['uid'] = (trim($r->uid)) ? trim($r->uid) : null; + $data['firstname'] = (trim($r->firstname)) ? trim($r->firstname) : null; + $data['lastname'] = (trim($r->lastname)) ? trim($r->lastname) : null; + $data['street'] = (trim($r->street)) ? trim($r->street) : null; + $data['housenumber'] = (trim($r->housenumber)) ? trim($r->housenumber) : null; + $data['block'] = (trim($r->block)) ? trim($r->block) : null; + $data['stiege'] = (trim($r->stiege)) ? trim($r->stiege) : null; + $data['stock'] = (trim($r->stock)) ? trim($r->stock) : null; + $data['tuer'] = (trim($r->tuer)) ? trim($r->tuer) : null; + $data['zip'] = (trim($r->zip)) ? trim($r->zip) : null; + $data['city'] = (trim($r->city)) ? trim($r->city) : null; + $data['phone'] = (trim($r->phone)) ? trim($r->phone) : null; + $data['email'] = (trim($r->email)) ? trim($r->email) : null; + $data['note'] = (trim($r->note)) ? trim($r->note) : null; $data['edit_by'] = $this->me->id; @@ -263,16 +311,173 @@ class PreorderController extends mfBaseController { } else { $preorder->update($data); } - - /* - * validation - */ $campaign = new Preordercampaign($preorder->preordercampaign_id); if(!$campaign->id) { $this->layout()->setFlash("Keine Kampagne ausgewählt!", "error"); $this->redirect("Preordercampaign"); } + //var_dump($preorder, $r);exit; + // handle new address creation + if(!$preorder->adb_hausnummer_id) { + // check if new address was submitted + $this->log->debug("check if new address was submitted"); + if($r->new_address_street && $r->new_address_housenumber && $r->new_address_zip && $r->new_address_city && $r->new_address_district) { + $city_search = trim($r->new_address_city); + $district_search = trim($r->new_address_district); + $zip_search = trim($r->new_address_zip); + $street_search = trim($r->new_address_street); + $housenumber_search = trim($r->new_address_housenumber); + + $block = trim($r->new_address_block); + $stiege = trim($r->new_address_stiege); + $stock = trim($r->new_address_stock); + $tuer = trim($r->new_address_tuer); + + $preorder->new_address_city = $city_search; + $preorder->new_address_district = $district_search; + $preorder->new_address_zip = $zip_search; + $preorder->new_address_street = $street_search; + $preorder->new_address_housenumber = $housenumber_search; + + + $netzgebiet_ids = []; + foreach($campaign->salesclusters as $scluster) { + $netzgebiet_ids[] = $scluster->id; + } + $netzgebiet_id = $netzgebiet_ids[0]; + if(!$netzgebiet_id) { + $this->layout()->setFlash("Kann Adresse nicht updaten: Kampagne hat kein Netzgebiet", "error"); + $this->layout()->set("preorder", $preorder); + $this->layout()->set("campaign", $campaign); + return $this->addAction(); + } + $netzgebiet = new ADBNetzgebiet($netzgebiet_id); + if(!$netzgebiet->id) { + $this->layout()->setFlash("Neztgebiet nicht gefunden", "error"); + $this->layout()->set("preorder", $preorder); + $this->layout()->set("campaign", $campaign); + return $this->addAction(); + } + + $city = ADBGemeindeModel::getFirst(['name' => $city_search, 'netzgebiet_id' => $netzgebiet_id]); + if(!$city) { + $this->layout()->setFlash("Gemeinde nicht Adress-DB gefunden", "error"); + $this->layout()->set("preorder", $preorder); + $this->layout()->set("campaign", $campaign); + return $this->addAction(); + } + + $district = ADBOrtschaftModel::getFirst(['name' => $district_search, 'netzgebiet_id' => $netzgebiet_id]); + if(!$district) { + $this->layout()->setFlash("Ortsteil nicht Adress-DB gefunden", "error"); + $this->layout()->set("preorder", $preorder); + $this->layout()->set("campaign", $campaign); + return $this->addAction(); + } + + $zip = ADBPlzModel::getFirst(['plz' => $zip_search, 'gemeinde_id' => $city->id]); + if(!$zip) { + $this->layout()->setFlash("PLZ nicht Adress-DB gefunden", "error"); + $this->layout()->set("preorder", $preorder); + $this->layout()->set("campaign", $campaign); + return $this->addAction(); + } + + $street = ADBStrasseModel::getFirst(['name' => $street_search, 'gemeinde_id' => $city->id]); + if(!$street) { + $this->log->debug("create street"); + $street = ADBStrasseModel::create([ + 'ortschaft_id' => $district->id, + 'gemeinde_id' => $city->id, + 'name' => $street_search + ]); + + if(!$street->save()) { + $this->layout()->setFlash("Fehler beim Speichern der neuen Straße", "error"); + $this->layout()->set("preorder", $preorder); + $this->layout()->set("campaign", $campaign); + return $this->addAction(); + } + } + + + $this->log->debug("search hausnummer"); + $hausnummer = ADBHausnummerModel::getFirst(['netzgebiet_id' => $netzgebiet_ids, 'ortschaft_id' => $district_search, 'gemeinde_id' => $city->id, 'plz_id' => $zip->id, 'strasse_id' => $street->id, 'hausnummer' => $housenumber_search]); + if($hausnummer) { + // hausnummer gibts scho! + $this->layout()->setFlash("Adresse war schon vorhanden!", "warn"); + $preorder->adb_hausnummer_id = $hausnummer->id; + } else { + // try with empty netzgebiet + $this->log->debug("search hausnummer mit empty netzgebiet"); + $hausnummer = ADBHausnummerModel::getFirst(['netzgebiet_id' => null, 'ortschaft_id' => $district_search, 'gemeinde_id' => $city->id, 'plz_id' => $zip->id, 'strasse_id' => $street->id, 'hausnummer' => $housenumber_search]); + if($hausnummer) { + // Hausnummer ohne Netzgebiet gefunden -> update netzgebiet_id + $this->log->debug("hausnummer id: updated netzgebiet from NULL to ".$netzgebiet_ids); + $hausnummer->netzgebiet_id = $netzgebiet_id; + $hausnummer->save(); + $preorder->adb_hausnummer_id = $hausnummer->id; + } else { + // try with any netzgebiet + $this->log->debug("search hausnummer with ohne netzgebiet"); + $hausnummer = ADBHausnummerModel::getFirst(['ortschaft_id' => $district_search, 'gemeinde_id' => $city->id, 'plz_id' => $zip->id, 'strasse_id' => $street->id, 'hausnummer' => $housenumber_search]); + if($hausnummer) { + $this->log->debug("Hausnummer ".$hausnummer->id." in Netzgebiet (".implode(",", $netzgebiet_ids)." gesucht, aber in ".$hausnummer->netzgebiet_id)." gefunden"; + $this->layout()->setFlash("Neue Adresse ist bereits im Netzgebiet ".$hausnummer->netzgebiet->name." vorhanden", "error"); + $this->layout()->set("preorder", $preorder); + $this->layout()->set("campaign", $campaign); + return $this->addAction(); + } else { + // hausnummer anlegen + $hausnummer = ADBHausnummerModel::create([ + 'netzgebiet_id' => $netzgebiet_id, + 'ortschaft_id' => $district->id, + 'plz_id' => $zip->id, + 'strasse_id' => $street->id, + 'hausnummer' => $housenumber_search, + 'freigabe' => $netzgebiet->freigabe, + 'manual_add' => date('U'), + 'manual_add_by' => $this->me->id, + 'manual_add_info' => "thetool user ".$this->me->username." via Preorder create" + ]); + + if(!$hausnummer->save()) { + $this->layout()->setFlash("Fehler beim Speichern der neuen Adresse", "error"); + $this->layout()->set("preorder", $preorder); + $this->layout()->set("campaign", $campaign); + return $this->addAction(); + } + $preorder->adb_hausnummer_id = $hausnummer->id; + $preorder->address_created = date('U'); + $preorder->address_created_by = $this->me->id; + $preorder->adb_wohneinheit_id = null; + + // create wohneinheit + $wohneinheit = ADBWohneinheitModel::create([ + 'hausnummer_id' => $hausnummer->id, + 'num' => 1, + 'block' => ($block) ? $block : null, + 'stiege' => ($stiege) ? $stiege : null, + 'stock' => ($stock) ? $stock : null, + 'tuer' => ($tuer) ? $tuer : null + ]); + if($wohneinheit->save()) { + $preorder->adb_wohneinheit_id = $wohneinheit->id; + } else { + $this->layout()->setFlash("Konnte Wohneinheit nicht speichern", "warn"); + } + + } + } + } + + } + } + + /* + * validation + */ if(!array_key_exists($data['type'], $campaign->types)) { $this->layout()->setFlash("Bitte Vorbestelltyp auswählen!", "error"); @@ -324,6 +529,12 @@ class PreorderController extends mfBaseController { //var_dump($preorder);exit; + // unset temporary properties + unset($preorder->new_address_city); + unset($preorder->new_address_district); + unset($preorder->new_address_zip); + unset($preorder->new_address_street); + unset($preorder->new_address_housenumber); /* * generate ucode and save @@ -337,7 +548,7 @@ class PreorderController extends mfBaseController { } - $qs = ['filter' => ['campaign_id' => $preorder->preordercampaign_id]]; + $qs = ['filter' => ['preordercampaign_id' => $preorder->preordercampaign_id, 'ucode' => $preorder->ucode]]; $qs = http_build_query($qs); $this->layout()->setFlash("Vorbestellung erfolgreich gespeichert!", "success"); diff --git a/application/Preorder/PreorderModel.php b/application/Preorder/PreorderModel.php index f9c966c82..ad0708014 100644 --- a/application/Preorder/PreorderModel.php +++ b/application/Preorder/PreorderModel.php @@ -2,9 +2,12 @@ class PreorderModel { public $ucode; + public $status_id; public $preordercampaign_id; public $adb_hausnummer_id; public $adb_wohneinheit_id; + public $oaid; + public $address_district; public $address_info; public $building_id; public $termination_id; @@ -31,15 +34,32 @@ class PreorderModel { public $firstname; public $lastname; public $street; + public $housenumber; + public $block; + public $stiege; + public $stock; + public $tuer; + public $unit_string; public $zip; public $city; public $phone; public $email; + public $technology; + public $patchposition; + public $is_additional_order; + public $shipping_address; public $addon_services; public $addon_data; public $submit_type; public $submit_request; + public $cancel_request; + public $cancel_request_by; + public $cancel_approved; + public $cancel_approved_by; + public $deleted; + public $deleted_by; + public $note; public $create_by; @@ -93,11 +113,26 @@ class PreorderModel { } - public static function getFirst() { + public static function getFirst($filter = false, $order = false) { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); - $res = $db->select("Preorder", "*", "$where ORDER BY lastname, firstname"); + + $orderBy = "lastname, firstname"; + if($order) $orderBy = $order; + + $sql = "SELECT tt_preorder.* FROM `".FRONKDB_DBNAME."`.Preorder tt_preorder + LEFT JOIN `".FRONKDB_DBNAME."`.Preorderstatus tt_preorderstatus ON (tt_preorder.status_id = tt_preorderstatus.id) + LEFT JOIN `".ADDRESSDB_DBNAME."`.view_hausnummer as adb_hausnummer ON (tt_preorder.adb_hausnummer_id = adb_hausnummer.hausnummer_id) + WHERE $where + ORDER BY $orderBy + LIMIT 1 + "; + + mfLoghandler::singleton()->debug($sql); + + $res = $db->query($sql); + if($db->num_rows($res)) { $data = $db->fetch_object($res); $item = new Preorder($data); @@ -110,6 +145,71 @@ class PreorderModel { return null; } + public static function countOrderedAddonservices($filter) { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $sql = "SELECT COUNT(*) AS cnt FROM `".FRONKDB_DBNAME."`.Preorder tt_preorder + LEFT JOIN `".ADDRESSDB_DBNAME."`.view_hausnummer as adb_hausnummer ON (tt_preorder.adb_hausnummer_id = adb_hausnummer.hausnummer_id), + JSON_TABLE(addon_services, + '$[*]' COLUMNS ( + ordered VARCHAR(64) PATH '$.ordered' + ) + ) a_services + WHERE $where + AND addon_services IS NOT NULL AND (a_services.ordered = 'true' OR a_services.ordered=1) + GROUP BY tt_preorder.id + "; + + mfLoghandler::singleton()->debug($sql); + + $res = $db->query($sql); + if($db->num_rows($res)) { + $data = $db->fetch_object($res); + return $data->cnt; + } + return 0; + } + + public static function searchOrderedAddonservices($filter, $limit = false) { + $items = []; + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + + $sql = "SELECT tt_preorder.* FROM `".FRONKDB_DBNAME."`.Preorder tt_preorder + LEFT JOIN `".ADDRESSDB_DBNAME."`.view_hausnummer as adb_hausnummer ON (tt_preorder.adb_hausnummer_id = adb_hausnummer.hausnummer_id), + JSON_TABLE(addon_services, + '$[*]' COLUMNS ( + ordered VARCHAR(64) PATH '$.ordered' + ) + ) a_services + WHERE $where + AND addon_services IS NOT NULL AND (a_services.ordered = 'true' OR a_services.ordered=1) + GROUP BY tt_preorder.id + ORDER BY lastname, firstname + + "; + + if(is_array($limit) && count($limit)) { + if(is_numeric($limit['start']) && is_numeric($limit['count'])) { + $sql .= " LIMIT ".$limit['start'].", ".$limit['count']; + } elseif(is_numeric($count)) { + $sql .= " LIMIT ".$limit['count']; + } + } + + mfLoghandler::singleton()->debug($sql); + + $res = $db->query($sql); + if($db->num_rows($res)) { + while($data = $db->fetch_object($res)) { + $items[] = new Preorder($data); + } + } + return $items; + } + public static function count($filter) { $db = FronkDB::singleton(); @@ -136,6 +236,7 @@ class PreorderModel { $where = self::getSqlFilter($filter); $sql = "SELECT tt_preorder.* FROM `".FRONKDB_DBNAME."`.Preorder tt_preorder + LEFT JOIN `".FRONKDB_DBNAME."`.Preorderstatus tt_preorderstatus ON (tt_preorder.status_id = tt_preorderstatus.id) LEFT JOIN `".ADDRESSDB_DBNAME."`.view_hausnummer as adb_hausnummer ON (tt_preorder.adb_hausnummer_id = adb_hausnummer.hausnummer_id) WHERE $where ORDER BY lastname, firstname @@ -172,10 +273,63 @@ class PreorderModel { } } + if(array_key_exists("partner_id", $filter)) { + $partner_id = $filter['partner_id']; + if(is_numeric($partner_id)) { + $where .= " AND partner_id=$partner_id"; + } + } + + if(array_key_exists("status_id", $filter)) { + $status_id = $filter['status_id']; + if(is_numeric($status_id)) { + $where .= " AND status_id=$status_id"; + } + } + + if(array_key_exists("status_id", $filter)) { + $status_id = $filter['>status_id']; + if(is_numeric($status_id)) { + $where .= " AND status_id > $status_id"; + } + } + + + if(array_key_exists("status_code", $filter)) { + $status_code = $filter['status_code']; + if(is_numeric($status_code)) { + $where .= " AND tt_preorderstatus.code=$status_code"; + } + } + + if(array_key_exists("status_code", $filter)) { + $status_code = $filter['>status_code']; + if(is_numeric($status_code)) { + $where .= " AND tt_preorderstatus.code > $status_code"; + } + } + + if(array_key_exists("preordercampaign_id", $filter)) { $preordercampaign_id = $filter['preordercampaign_id']; if(is_numeric($preordercampaign_id)) { $where .= " AND preordercampaign_id=$preordercampaign_id"; + } elseif(is_array($preordercampaign_id) && count($preordercampaign_id)) { + $where .= " AND preordercampaign_id IN (". implode(",", $preordercampaign_id).")"; } } @@ -212,6 +366,15 @@ class PreorderModel { } } + if(array_key_exists("address_created", $filter)) { + $address_created = $filter['address_created']; + if($address_created === true) { + $where .= " AND address_created > 0"; + } elseif($address_created == null) { + $where .= " AND address_created IS NULL"; + } + } + if(array_key_exists("type", $filter)) { $type = $filter['type']; if(is_array($type) && count($type)) { @@ -224,13 +387,31 @@ class PreorderModel { } } - if(array_key_exists("ucode", $filter)) { - $ucode = FronkDB::singleton()->escape($filter['ucode']); - if($ucode) { - $where .= " AND ucode like '%$ucode%'"; + if(array_key_exists("connection_type", $filter)) { + $connection_type = $filter['connection_type']; + if(is_array($connection_type) && count($connection_type)) { + $where .= " AND connection_type IN ('".implode("','",$connection_type)."')"; + } else { + $connection_type = FronkDB::singleton()->escape($filter['connection_type']); + if($connection_type) { + $where .= " AND connection_type like '%$connection_type%'"; + } } } + if(array_key_exists("ucode", $filter)) { + $ucode = FronkDB::singleton()->escape($filter['ucode']); + if($ucode) { + $where .= " AND ucode = '$ucode'"; + } + } + + if(array_key_exists("oaid", $filter)) { + $oaid = FronkDB::singleton()->escape($filter['oaid']); + if($oaid) { + $where .= " AND tt_preorder.oaid = '$oaid'"; + } + } if(array_key_exists("gemeinde", $filter)) { $gemeinde = FronkDB::singleton()->escape($filter['gemeinde']); @@ -253,6 +434,7 @@ class PreorderModel { } } + // custom where clause if(array_key_exists("add-where", $filter)) { $where .= " ".$filter['add-where']; } diff --git a/application/Preordercampaign/Preordercampaign.php b/application/Preordercampaign/Preordercampaign.php index 0dba43ab3..af3dbc792 100644 --- a/application/Preordercampaign/Preordercampaign.php +++ b/application/Preordercampaign/Preordercampaign.php @@ -139,7 +139,7 @@ class Preordercampaign extends mfBaseModel { if($name == "salesclusters") { $items = PreordercampaignSalesclusterModel::search(["preordercampaign_id" => $this->id]); foreach($items as $pog) { - $this->salesclusters[$pog->salescluster_id] = $pog; + $this->salesclusters[$pog->salescluster_id] = new ADBNetzgebiet($pog->salescluster_id); } return $this->salesclusters; } diff --git a/application/Preordercampaign/PreordercampaignController.php b/application/Preordercampaign/PreordercampaignController.php index 5689cb895..0398a1800 100644 --- a/application/Preordercampaign/PreordercampaignController.php +++ b/application/Preordercampaign/PreordercampaignController.php @@ -9,7 +9,7 @@ class PreordercampaignController extends mfBaseController { $this->me = $me; $this->layout()->set("me",$me); - if(!$me->is(["Admin", "salespartner"])) { + if(!$me->is(["Admin", "netowner", "salespartner"])) { $this->redirect("Dashboard"); } } @@ -19,6 +19,7 @@ class PreordercampaignController extends mfBaseController { $this->layout->set("filter", $this->request->filter); + $filter = []; if($this->request->filter) { $filter = $this->getPreparedFilter($this->request->filter); } @@ -34,43 +35,75 @@ class PreordercampaignController extends mfBaseController { } $my_networks = []; - + //var_dump($filter);exit; if($this->me->is("Admin")) { - if($filter['network_id']) { + if(!is_array($filter['network_id']) && $filter['network_id']) { $my_networks[] = new Network($filter['network_id']); } else { $my_networks = NetworkModel::getAll(); } $this->layout()->set("mynetworks", NetworkModel::getAll()); + + $netowners = $this->getNetworkOwners($my_network_ids); + $this->layout()->set("netowners", $netowners); + } else { $use_filter_network = false; - $my_networks = $this->me->my_networks; - + $my_networks = $this->me->myNetworks(["netowner", "salespartner"]); + //var_dump($my_networks);exit; foreach($my_networks as $mn) { if($mn->id == $filter['network_id']) { $use_filter_network = true; - continue; + break; } } + $this->layout()->set("mynetworks", $my_networks); + if($use_filter_network) { $my_networks = []; $my_networks[] = new Network($filter['network_id']); } - $this->layout()->set("mynetworks", $this->me->my_networks); - + $my_network_ids = []; + foreach($my_networks as $network) { + $my_network_ids[] = $network->id; + } + $filter['network_id'] = $my_network_ids; } - unset($filter['network_id']); - $campaigns = PreordercampaignModel::search(['network_id' => $my_networks]); + + + $campaigns = PreordercampaignModel::search($filter); $this->layout()->set("campaigns", $campaigns); + } private function getPreparedFilter($filter) { $new_filter = []; + if(array_key_exists("netowner", $filter) && $filter['netowner']) { + if($this->me->is("Admin")) { + $owner_id = $filter['netowner']; + foreach(NetworkModel::search(['owner_id' => $owner_id]) as $network) { + $new_filter['network_id'][] = $network->id; + } + unset($filter['network_id']); + } else { + unset($filter['netowner']); + } + } + + if(array_key_exists("name", $filter) && $filter['name']) { + $new_filter['name%'] = "%".$filter['name']; + unset($filter['name']); + } + if(array_key_exists("area", $filter) && $filter['area']) { + $new_filter['area%'] = "%".$filter['area']; + unset($filter['area']); + } + foreach($filter as $name => $value) { $new_filter[$name] = $value; } @@ -78,7 +111,30 @@ class PreordercampaignController extends mfBaseController { return $new_filter; } + private function getNetworkOwners() { + $owners = []; + + $sql = "SELECT Address.* FROM Preordercampaign + LEFT JOIN Network ON (Preordercampaign.network_id = Network.id) + LEFT JOIN Address ON (Network.owner_id = Address.id) + GROUP BY Address.id + ORDER BY Address.company, Address.lastname, Address.firstname + "; + $res = $this->db()->query($sql); + if($this->db()->num_rows($reso)) { + while($data = $this->db()->fetch_object($res)) { + $owners[] = new Address($data->id); + } + } + + return $owners; + } + protected function addAction() { + if(!$this->me->is("Admin")) { + $this->redirect("Preordercampaign"); + } + $this->layout()->setTemplate("Preordercampaign/Form"); if($this->me->isAdmin()) { @@ -98,6 +154,10 @@ class PreordercampaignController extends mfBaseController { } protected function editAction() { + if(!$this->me->is("Admin")) { + $this->redirect("Preordercampaign"); + } + $id = $this->request->id; if(!is_numeric($id) || !$id) { $this->layout()->setFlash("Vorbestellkampagne nicht gefunden", "error"); @@ -116,6 +176,10 @@ class PreordercampaignController extends mfBaseController { } protected function saveAction() { + if(!$this->me->is("Admin")) { + $this->redirect("Preordercampaign"); + } + $r = $this->request; //var_dump($r);exit; $id = $r->id; @@ -173,6 +237,23 @@ class PreordercampaignController extends mfBaseController { $data['required_preorder_fields'] = null; } + if($r->district_is_city == 1) { + $data['district_is_city'] = 1; + } else { + $data['district_is_city'] = 0; + } + + if($r->hausnummer_add_zusatz == 1) { + $data['hausnummer_add_zusatz'] = 1; + } else { + $data['hausnummer_add_zusatz'] = 0; + } + + if($r->exist_is_error == 1) { + $data['exist_is_error'] = 1; + } else { + $data['exist_is_error'] = 0; + } $data['edit_by'] = $this->me->id; @@ -246,5 +327,84 @@ class PreordercampaignController extends mfBaseController { $this->redirect("Preordercampaign"); } - + + protected function downloadAddonServices() { + $id = $this->request->preordercampaign_id; + if(!is_numeric($id) || !$id) { + $this->layout()->setFlash("Vorbestellkampagne nicht gefunden", "error"); + $this->redirect("Preordercampaign"); + } + + $campaign = new Preordercampaign($id); + if(!$campaign->id) { + $this->layout()->setFlash("Vorbestellkampagne nicht gefunden", "error"); + $this->redirect("Preordercampaign"); + } + + $this->layout()->set("campaign", $campaign); + $preorders = PreorderModel::search(["preordercampaign_id" => $id, "add-where" => "AND JSON_LENGTH(addon_services) > 1"]); + + if(!count($preorders)) { + $this->layout->setFlash("Keine Vorbestellungen mit bestellten Dienstleistungen gefunden."); + $this->redirect("Preordercampaign"); + } + + $csv = []; + foreach($preorders as $preorder) { + $sjson = json_decode($preorder->addon_services); + if(!$sjson) { + continue; + } + + // address data and stuff + $general = [ + "ucode" => $preorder->ucode, + "gemeinde" => $preorder->adb_hausnummer->ortschaft->gemeinde->name, + "plz" => $preorder->adb_hausnummer->plz->plzstring, + "ortschaft" => $preorder->adb_hausnummer->ortschaft->name, + "strasse" => $preorder->adb_hausnummer->strasse->name, + "hausnummer" => $preorder->adb_hausnummer->hausnummer, + "block" => "", + "stiege" => "", + "stock" => "", + "tuer" => "", + "zusatz" => "", + "address_info" => $preorder->address_info, + "contact_firma" => $preorder->company, + "contact_uid" => $preorder->uid, + "contact_firstname" => $preorder->firstname, + "contact_lastname" => $preorder->lastname, + "contact_street" => $preorder->street, + "contact_plz" => $preorder->zip, + "contact_ort" => $preorder->city, + "phone" => $preorder->phone, + "email" => $preorder->email, + ]; + + if($preorder->adb_wohneinheit_id) { + $general["block"] = $preorder->adb_wohneinheit->block; + $general["stiege"] = $preorder->adb_wohneinheit->stiege; + $general["stock"] = $preorder->adb_wohneinheit->stock; + $general["tuer"] = $preorder->adb_wohneinheit->tuer; + $general["zusatz"] = $preorder->adb_wohneinheit->zusatz; + } + + foreach($sjson as $service) { + if(!$service->ordered) continue; + + $s = $general; + $s["service"] = $service->service; + $data = []; + foreach($service->data as $d) { + $data[] = (string)$d->name.": ".(is_bool($d->value) ? (int)$d->value : (string)$d->value); + } + $s["service_data"] = implode("; ", $data); + $csv[] = $s; + } + //var_dump($csv);exit; + $this->layout()->setTemplate("Preordercampaign/services.csv"); + $this->layout()->set("csv", $csv); + } + + } } \ No newline at end of file diff --git a/application/Preordercampaign/PreordercampaignModel.php b/application/Preordercampaign/PreordercampaignModel.php index 71225b81d..b742e7331 100644 --- a/application/Preordercampaign/PreordercampaignModel.php +++ b/application/Preordercampaign/PreordercampaignModel.php @@ -3,12 +3,19 @@ class PreordercampaignModel { public $name; public $network_id; + public $homes_count; public $fulfillment; + public $product_type; public $description; public $area; public $from; public $to; - + public $required_preorder_fields; + public $district_is_city; + public $hausnummer_add_zusatz; + public $exist_is_error; + public $require_connectiontype; + public $allow_unit_update; public $note; public $create_by; @@ -79,6 +86,12 @@ class PreordercampaignModel { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); + + $sql = "SELECT Preordercampaign.* FROM Preordercampaign + LEFT JOIN Network on (Preordercampaign.network_id = Network.id) + WHERE $where ORDER BY name,`create` + "; + mfLoghandler::singleton()->debug($sql); $res = $db->select("Preordercampaign", "*", "$where ORDER BY name,`create`"); if($db->num_rows($res)) { while($data = $db->fetch_object($res)) { @@ -90,17 +103,54 @@ class PreordercampaignModel { private static function getSqlFilter($filter) { $where = "1=1 "; - + //var_dump($filter);exit; if(array_key_exists("network_id", $filter)) { - $networkid = $filter['network_id']; - if(is_numeric($networkid)) { - $where .= " AND network_id=$networkid"; + $network_id = $filter['network_id']; + if(is_numeric($network_id)) { + $where .= " AND network_id=$network_id"; } elseif(is_array($network_id) && count($network_id)) { $where .= " AND network_id IN (". implode(",", $network_id).")"; } } + if(array_key_exists("owner_id", $filter)) { + $owner_id = $filter['owner_id']; + if(is_numeric($owner_id)) { + $where .= " AND Network.owner_id=$owner_id"; + } elseif(is_array($owner_id) && count($owner_id)) { + $where .= " AND Network.owner_id IN (". implode(",", $owner_id).")"; + } + } + + if(array_key_exists("name", $filter)) { + $name = FronkDB::singleton()->escape($filter['name']); + if($name) { + $where .= " AND `name` = '$name'"; + } + } + + if(array_key_exists("name%", $filter)) { + $name = FronkDB::singleton()->escape($filter['name%']); + if($name) { + $where .= " AND `name` LIKE '$name%'"; + } + } + + if(array_key_exists("area", $filter)) { + $area = FronkDB::singleton()->escape($filter['area']); + if($area) { + $where .= " AND `area` = '$area'"; + } + } + + if(array_key_exists("area%", $filter)) { + $area = FronkDB::singleton()->escape($filter['area%']); + if($area) { + $where .= " AND `area` LIKE '$area%'"; + } + } + //var_dump($filter, $where);exit; return $where; } diff --git a/application/Preordernotification/Preordernotification.php b/application/Preordernotification/Preordernotification.php new file mode 100644 index 000000000..42e71cfa5 --- /dev/null +++ b/application/Preordernotification/Preordernotification.php @@ -0,0 +1,200 @@ +preordercampaign_id) return false; + + $preorder_filter = json_decode($this->preorder_filter, true); + $preorder_filter['preordercampaign_id'] = $this->preordercampaign_id; + + $preorders = PreorderModel::search($preorder_filter); + return $preorders; + } + + public function sendToPreorder(Preorder $preorder, $email_to = false) { + $subject = $this->subject; + $body = $this->replaceBodyVariables($this->body_html, $preorder); // TODO: Variable replacement + + // TODO: Extract text part + + //var_dump($body);exit; + $from = $this->sender_email; + $from_name = $this->sender_name; + $reply_to = null; + if($this->sender_replyto) { + $reply_to = $this->sender_replyto; + } + + $to = $preorder->email; + + if($email_to) { + $to = $email_to; + } else { + // check if email was sent to this preorder already + $log = PreordernotificationLogModel::getFirst([ + 'preordernotification_id' => $this->id, + 'preorder_id' => $preorder->id + ]); + + if(!$log) { + // check if this was sent to the same emailaddress already + $log = PreordernotificationLogModel::getFirst([ + 'preordernotification_id' => $this->id, + 'email' => $preorder->email + ]); + } + + if($log) { + return true; + } + } + + if(!$to) return true; + + // get attachments + $attachments = []; + foreach($this->getProperty("files") as $file) { + $att = []; + $att["path"] = MFUPLOAD_FILE_SAVE_PATH."/".$file->file->subfolder."/".$file->file->store_filename; + $att["filename"] = $file->filename; + $att["mimetype"] = $file->file->mimetype; + $attachments[] = $att; + } + + //var_dump($attachments);exit; + + if(!$subject || !$from || !$from_name || !$to) { + $this->log->warn("Preordernotification not sent. subject, from or to missing. Preorder id ".$preorder->id); + return false; + } else { + $email = new Emailnotification(); + $email->setSubject($subject); + $email->setHtmlBody($body); + $email->setFrom($from, $from_name); + $email->setTo($to); + if($reply_to) { + $email->setHeader("Reply-To", $reply_to); + } + $email->setHeader("X-".ucfirst(MFAPPNAME)."-Pnid", $this->id); + if(count($attachments)) { + foreach($attachments as $file) { + $email->addAttachment($file["path"], null, $file["filename"], $file['mimetype']); + } + } + $email->send(); + $this->log->info(__CLASS__."::sendToPreorder(): Sending Preordernotification for Preorder id ".$preorder->id); + + if($preorder && !$email_to) { + // save notification log + $log = PreordernotificationLogModel::create([ + 'preordernotification_id' => $this->id, + 'preorder_id' => $preorder->id, + 'email' => $preorder->email, + 'sent' => date('U') + ]); + $log->save(); + } + } + + return true; + } + + private function replaceBodyVariables($body, $preorder) { + $fullname = ""; + if($preorder->firstname) { + $fullname = $preorder->firstname; + if($preorder->lastname) { + $fullname .= " ".$preorder->lastname; + } + } elseif($preorder->lastname) { + $fullname = $preorder->lastname; + } + + $replacers = [ + 'VORNAME' => $preorder->firstname, + 'NACHNAME' => $preorder->nachname, + 'FIRMA' => $preorder->company, + 'FIRMA_ODER_NAME' => ($preorder->company) ? $preorder->company : $fullname, + 'EMAIL' => $preorder->email, + 'ANSCHLUSS_OAID' => ($preorder->adb_wohneinheit_id) ? $preorder->adb_wohneinheit->oaid : $preorder->adb_hausnummer->oaid, + 'ANSCHLUSS_STRASSE' => $preorder->adb_hausnummer->strasse->name, + 'ANSCHLUSS_HAUSNUMMER' => $preorder->adb_hausnummer->hausnummer, + 'ANSCHLUSS_PLZ' => $preorder->adb_hausnummer->plz->plz, + 'ANSCHLUSS_ORT' => $preorder->adb_hausnummer->ortschaft->name, + 'ANSCHLUSS_GEMEINDE' => $preorder->adb_hausnummer->strasse->gemeinde->name, + 'PREORDER_CODE' => $preorder->ucode + + ]; + + foreach($replacers as $key => $replacement) { + $body = str_replace("{{".$key."}}", $replacement, $body); + } + + return $body; + } + + public function getProperty($name) { + if($this->$name == null) { + + if($name == "campaign") { + $this->campaign = new Preordercampaign($this->preordercampaign_id); + return $this->campaign; + } + + if($name == "filter") { + if($this->preorder_filter) { + $this->filter = json_decode($this->preorder_filter, true); + } else { + $this->filter = []; + } + return $this->filter; + } + + if($name == "files") { + $this->files = PreordernotificationFileModel::search(["preordernotification_id" => $this->id]); + return $this->files; + } + + if($name == "creator") { + $user = mfValuecache::singleton()->get("Worker-id-".$this->create_by); + if($user) { + $this->creator = $user; + return $this->creator; + } + $this->creator = new User($this->create_by); + if($this->creator->id) { + mfValuecache::singleton()->set("Worker-id-".$this->create_by, $this->creator); + } + return $this->creator; + } + + if($name == "editor") { + $this->editor = new User($this->edit_by); + return $this->editor; + } + + $classname = ucfirst($name); + $idfield = $name."_id"; + $this->$name = mfValuecache::singleton()->get("mfObjectmodel-$name-".$this->$idfield); + if(!$this->$name) { + $this->$name = new $classname($this->$idfield); + } + + if($this->$name->id) { + mfValuecache::singleton()->set("mfObjectmodel-$name-".$this->$name->id, $this->$name); + return $this->$name; + } else { + return null; + } + } + + return $this->$name; + } +} \ No newline at end of file diff --git a/application/Preordernotification/PreordernotificationController.php b/application/Preordernotification/PreordernotificationController.php new file mode 100644 index 000000000..e38a09952 --- /dev/null +++ b/application/Preordernotification/PreordernotificationController.php @@ -0,0 +1,389 @@ +needlogin=true; + $me = new User(); + $me->loadMe(); + $this->me = $me; + $this->layout()->set("me",$me); + + if(!$me->is(["Admin", "netowner", "salespartner"])) { + $this->redirect("Dashboard"); + } + } + + protected function indexAction() { + $this->layout()->setTemplate("Preordernotification/Index"); + + $rfilter = $this->request->filter; + iF(!is_array($rfilter)) { + $rfilter = []; + } + + $this->layout->set("filter", $rfilter); + + $where = ""; + $filter = $this->getPreparedFilter($rfilter); + + // pagination defaults + $pagination = []; + $pagination['start'] = 0; + $pagination['count'] = 25; + $pagination['maxItems'] = 0; + + if(is_numeric($this->request->s)) { + $pagination['start'] = intval($this->request->s); + } + + $preorder_filter = $filter; + $my_campaigns = []; + $my_campaign_ids = []; + + if($this->me->is("Admin")) { + if($filter['preordercampaign_id']) { + $this->layout()->set("campaign", new Preordercampaign($filter['preordercampaign_id'])); + } else { + $my_campaigns = PreordercampaignModel::getAll(); + } + $this->layout()->set("my_campaigns", PreordercampaignModel::getAll()); + } else { + $my_networks = $this->me->myNetworks(["netowner", "salespartner"]); + //var_dump($my_networks);exit; + + foreach($my_networks as $network) { + foreach(PreordercampaignModel::search(['network_id' => $network->id]) as $campaign) { + $my_campaigns[] = $campaign; + if(!in_array($campaign->id, $my_campaign_ids)) $my_campaign_ids[] = $campaign->id; + } + } + //var_dump($my_network_ids,$my_campaign_ids);exit; + $this->layout()->set("my_campaigns", $my_campaigns); + + if($filter['preordercampaign_id'] && in_array($filter['preordercampaign_id'], $my_campaign_ids)) { + $campaign_id = $filter['preordercampaign_id']; + if(is_numeric($campaign_id) && $campaign_id > 0) { + $campaign = new Preordercampaign($campaign_id); + $this->layout()->set("campaign", $campaign); + } + } else { + $filter['preordercampaign_id'] = $my_campaign_ids; + } + } + //var_dump($filter);exit; + $pagination['maxItems'] = PreordernotificationModel::count($filter); + $notifications = PreordernotificationModel::search($filter, $pagination); + + $this->layout()->set("pagination", $pagination); + $this->layout()->set("notifications", $notifications); + + + } + + private function getPreparedFilter($filter) { + $new_filter = []; + + if(is_array($filter) && count($filter)) { + foreach($filter as $name => $value) { + $new_filter[$name] = $value; + } + } + + return $new_filter; + } + + protected function addAction() { + $this->layout()->setTemplate("Preordernotification/Form"); + if(!$this->request->preordercampaign_id) { + $this->layout()->setFlash("Keine Kampagne ausgewählt!", "warn"); + } + + $campaign_id = $this->request->preordercampaign_id; + $campaign = new Preordercampaign($campaign_id); + $this->layout()->set("campaign", $campaign); + + $partners = AddressModel::search(['addresstype' => ['netowner','salespartner']]); + $this->layout()->set("partners", $partners); + + } + + protected function editAction() { + $id = $this->request->id; + if(!is_numeric($id) || $id < 1) { + $this->layout()->setFlash("Aussendung nicht gefunden", "error"); + $this->redirect("Preordernotification"); + } + + $notification = new Preordernotification($id); + if(!$notification->id) { + $this->layout()->setFlash("Aussendung nicht gefunden", "error"); + $this->redirect("Preordernotification"); + } + + //var_dump($notification->filter);exit; + + $this->request->set("preordercampaign_id", $notification->preordercampaign_id); // needed in addAction() + $this->layout()->set("notification", $notification); + + return $this->addAction(); + + } + + protected function saveAction() { + $r = $this->request; + //var_dump($r->get(), $_FILES);exit; + + /* + * add or edit + */ + $id = $r->id; + if(is_numeric($id) && $id > 0) { + $mode = "edit"; + $notification = new Preordernotification($id); + if(!$notification->id) { + $this->layout()->setFlash("Aussendung nicht gefunden", "error"); + $this->redirect("Preordernotification"); + } + } else { + $id = false; + $mode = "add"; + } + + /* + * check campaign and permissions + */ + + $campaign_id = $r->preordercampaign_id; + if(!$campaign_id) { + $this->layout()->setFlash("Vorbestellkampagne nicht gefunden", "error"); + $this->redirect("Preordernotification"); + } + $campaign = new Preordercampaign($campaign_id); + if(!$campaign->id) { + $this->layout()->setFlash("Vorbestellkampagne nicht gefunden", "error"); + $this->redirect("Preordernotification"); + } + + // check permission + if(!$this->me->is("Admin")) { + $my_campaign_ids = []; + $my_networks = $this->me->myNetworks(["netowner", "salespartner"]); + //var_dump($my_networks);exit; + + foreach($my_networks as $network) { + foreach(PreordercampaignModel::search(['network_id' => $network->id]) as $campaign) { + if(!in_array($campaign->id, $my_campaign_ids)) $my_campaign_ids[] = $campaign->id; + } + } + + if(!in_array($campaign_id, $my_campaign_ids)) { + $this->layout()->setFlash("Vorbestellkampagne nicht gefunden", "error"); + $this->redirect("Preordernotification"); + } + } + + + /* + * data colletion + */ + $filter = []; + if(is_array($r->type) && count($r->type)) { + $filter['type'] = []; + foreach($r->type as $type) { + switch($type) { + case "interest": + $filter["type"][] = "interest"; + break; + case "provision": + $filter["type"][] = "provision"; + break; + case "order": + $filter["type"][] = "order"; + break; + case "reorder": + $filter["type"][] = "reorder"; + break; + } + } + } + + if(is_array($r->connection_type) && count($r->connection_type)) { + $filter['connection_type'] = []; + foreach($r->connection_type as $type) { + switch($type) { + case "single-dwelling": + $filter["connection_type"][] = "single-dwelling"; + break; + case "multi-dwelling": + $filter["connection_type"][] = "multi-dwelling"; + break; + case "apartment-building": + $filter["connection_type"][] = "apartment-building"; + break; + case "apartment": + $filter["connection_type"][] = "apartment"; + break; + case "business": + $filter["connection_type"][] = "business"; + break; + } + } + } + + //var_dump($filter); + $data = []; + $data['preordercampaign_id'] = $campaign_id; + $data['sender_email'] = $r->sender_email; + $data['sender_name'] = $r->sender_name; + $data['sender_replyto'] = $r->sender_replyto; + $data['subject'] = $r->subject; + $data['body_html'] = $r->body_html; + $data['note'] = $r->note; + + if($r->tosend_day) { + $tosend_day = $r->tosend_day; + $tosend_hour = $r->tosend_hour; + if($tosend_hour < 0 || $tosend_hour > 23) { + $tosend_hour = 0; + } + $data['tosend_date'] = self::dateToTimestamp($tosend_day." ".str_pad($tosend_hour, 2, "0", STR_PAD_LEFT).":00:00"); + } + + $data['preorder_filter'] = json_encode($filter); + + //var_dump($data);exit; + + if($mode == "edit") { + $notification->update($data); + } else { + $notification = PreordernotificationModel::create($data); + } + + $new_id = $notification->save(); + if(!$new_id) { + $this->layout()->setFlash("Fehler beim Speichern", "error"); + if($id) { + $this->redirect("Preordernotification", "edit", ['id' => $id]); + } else { + $this->redirect("Preordernotification"); + } + } + + /* + * Attachment upload + */ + + if(array_key_exists("attachment", $_FILES)) { + $files = $_FILES['attachment']; + if(is_array($files) && count($files)) { + $file_errors = 0; + foreach($files['name'] as $i => $name) { + if(!$name) continue; + $upload_error = false; + try { + $upload = new mfUpload(['attachment', $i]); + $upload->setSavepath(MFUPLOAD_FILE_SAVE_PATH . "/" . TT_PREORDERNOTIFICATION_FILE_UPLOAD_SUBFOLDER); + } catch(Exception $e) { + $this->layout()->setFlash("Dateiupload fehlgeschlagen: ".$e->getMessage(), "warn"); + $file_errors++; + continue; + } + + if(!$upload->getSize()) { + $this->layout()->setFlash("Dateiupload fehlgeschlagen: Datei ist leer!", "warn"); + $upload_error = true; + } + + $mime = ""; + + if(!$upload_error) { + try { + $mime = $upload->getMimetype(); + $upload->save(); + } catch(Exception $e) { + $this->layout()->setFlash("Dateiupload fehlgeschlagen", "warn"); + $upload_error = true; + } + } + + if($upload_error) { + $file_errors++; + continue; + } + + $file_data = []; + $file_data['name'] = $upload->getOriginalFilename(); + $file_data['filename'] = $upload->getOriginalFilename(); + $file_data['subfolder'] = TT_PREORDERNOTIFICATION_FILE_UPLOAD_SUBFOLDER; + $file_data['store_filename'] = $upload->getFilename(); + $file_data['orig_filename'] = $upload->getOriginalFilename(); + $file_data['mimetype'] = $mime; + + $file = FileModel::create($file_data); + $file_id = $file->save(); + if(!$file_id) { + $this->layout()->setFlash("Dateiupload fehlgeschlagen", "warn"); + unlink($upload->getSavepath()."/".$upload->getFilename()); + } else { + $pnf = []; + $pnf['preordernotification_id'] = $notification->id; + $pnf['file_id'] = $file_id; + $pnf['filename'] = $file->filename; + + $notification_file = PreordernotificationFileModel::create($pnf); + if(!$notification_file->save()) { + $file->delete(); + unlink($upload->getSavepath()."/".$upload->getFilename()); + $this->layout()->setFlash("Dateiupload fehlgeschlagen", "warn"); + } + + } + + } + } + + } + + /* + * delete files + */ + //var_dump($r->deletefile);exit; + if(is_array($r->deletefile)) { + foreach($r->deletefile as $pnf_id => $check) { + if(!$check) continue; + $pnf = new PreordernotificationFile($pnf_id); + if($pnf->preordernotification_id != $notification->id) continue; + $pnf->file->delete(); + $pnf->delete(); + } + } + + + // get and save preorder count + $preorder_filter = json_decode($notification->preorder_filter, true); + $preorder_filter['preordercampaign_id'] = $notification->preordercampaign_id; + $preorder_count = PreorderModel::count($preorder_filter); + $notification->recipient_count = $preorder_count; + $notification->save(); + + if($r->send_testmail && $r->testmail_to) { + $preorder = PreorderModel::getFirst($preorder_filter); + if(!$preorder) { + $this->layout()->setFlash("Testmail konnte nicht versendet werden. Keine Empfänger gefunden", "warn"); + $this->redirect("Preordernotification", "edit", ['id' => $new_id]); + } + $notification->sendToPreorder($preorder, $r->testmail_to); + $this->layout()->setFlash("Test Email erfolgreich versendet", "success"); + $this->redirect("Preordernotification", "edit", ['id' => $new_id]); + } + + $this->layout()->setFlash("Erfolgreich gepeichert.", "success"); + if($r->return == "index") { + $this->redirect("Preordernotification"); + } else { + $this->redirect("Preordernotification", "edit", ['id' => $new_id]); + } + + } +} \ No newline at end of file diff --git a/application/Preordernotification/PreordernotificationModel.php b/application/Preordernotification/PreordernotificationModel.php new file mode 100644 index 000000000..4334ada32 --- /dev/null +++ b/application/Preordernotification/PreordernotificationModel.php @@ -0,0 +1,180 @@ + $value) { + if(property_exists(get_called_class(), $field)) { + $model ->$field = $value; + } + } + + $me = new User(); + $me->loadMe(); + + if($model->create_by === null) { + $model->create_by = $me->id; + } + if($model->edit_by === null) { + $model->edit_by = $me->id; + } + + return $model; + } + + public static function getOne($id) { + if(!is_numeric($id) || !$id) { + throw new Exception("Invalid number", 400); + } + $item = []; + $db = FronkDB::singleton(); + + $res = $db->select("Preordernotification", "*", "id=$id LIMIT 1"); + if($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new Preordernotification($data); + } + return $item; + } + + public static function getAll() { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("Preordernotification", "*", "1 = 1 ORDER BY name,producttech_id"); + if($db->num_rows($res)) { + while($data = $db->fetch_object($res)) { + $items[] = new Preordernotification($data); + } + } + return $items; + + } + + public static function getFirst() { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("Preordernotification", "*", "$where ORDER BY producttech_id, name LIMIT 1"); + if($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new Preordernotification($data); + if($item->id) { + return $item; + } else { + return null; + } + } + return null; + } + + public static function count($filter) { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $sql = "SELECT COUNT(*) as cnt FROM `Preordernotification` + WHERE $where + "; + + mfLoghandler::singleton()->debug($sql); + $res = $db->query($sql); + if($db->num_rows($res)) { + $data = $db->fetch_object($res); + return $data->cnt; + } + return 0; + } + + public static function search($filter, $limit=false) { + $items = []; + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + + $sql = "SELECT Preordernotification.* FROM `Preordernotification` + WHERE $where + ORDER BY preordercampaign_id, `create` + "; + + mfLoghandler::singleton()->debug($sql); + if(is_array($limit) && count($limit)) { + if(is_numeric($limit['start']) && is_numeric($limit['count'])) { + $sql .= " LIMIT ".$limit['start'].", ".$limit['count']; + } elseif(is_numeric($count)) { + $sql .= " LIMIT ".$limit['count']; + } + } + + $res = $db->query($sql); + if($db->num_rows($res)) { + while($data = $db->fetch_object($res)) { + $items[] = new Preordernotification($data); + } + } + return $items; + } + + private static function getSqlFilter($filter) { + $where = "1=1 "; + + $db = FronkDB::singleton(); + + //var_dump($filter);exit; + if(array_key_exists("id", $filter)) { + $id = $db->escape($filter['id']); + if($id) { + $where .= " AND Preordernotification.`id` = '$id'"; + } + } + + if(array_key_exists("preordercampaign_id", $filter)) { + $preordercampaign_id = $filter['preordercampaign_id']; + if(is_numeric($preordercampaign_id)) { + $where .= " AND preordercampaign_id=$preordercampaign_id"; + } elseif(is_array($preordercampaign_id) && count($preordercampaign_id)) { + $where .= " AND Preordernotification.preordercampaign_id IN (". implode(",", $preordercampaign_id).")"; + } + } + + if(array_key_exists("send_finish", $filter)) { + $send_finish = $db->escape($filter['send_finish']); + if($send_finish === null) { + $where .= " AND Preordernotification.send_finish = NULL"; + } + } + + if(array_key_exists("send_lock", $filter)) { + $send_lock = $db->escape($filter['send_lock']); + if($send_lock === null) { + $where .= " AND Preordernotification.send_lock = NULL"; + } + } + + //var_dump($filter, $where);exit; + return $where; + } + +} \ No newline at end of file diff --git a/application/PreordernotificationFile/PreordernotificationFile.php b/application/PreordernotificationFile/PreordernotificationFile.php new file mode 100644 index 000000000..f6d6e9ee0 --- /dev/null +++ b/application/PreordernotificationFile/PreordernotificationFile.php @@ -0,0 +1,28 @@ +$name == null) { + + + $classname = ucfirst($name); + $idfield = $name."_id"; + $this->$name = mfValuecache::singleton()->get("mfObjectmodel-$name-".$this->$idfield); + if(!$this->$name) { + $this->$name = new $classname($this->$idfield); + } + + if($this->$name->id) { + mfValuecache::singleton()->set("mfObjectmodel-$name-".$this->$name->id, $this->$name); + return $this->$name; + } else { + return null; + } + } + + return $this->$name; + } +} \ No newline at end of file diff --git a/application/PreordernotificationFile/PreordernotificationFileModel.php b/application/PreordernotificationFile/PreordernotificationFileModel.php new file mode 100644 index 000000000..5734b0767 --- /dev/null +++ b/application/PreordernotificationFile/PreordernotificationFileModel.php @@ -0,0 +1,150 @@ + $value) { + if(property_exists(get_called_class(), $field)) { + $model ->$field = $value; + } + } + + $me = new User(); + $me->loadMe(); + + if($model->create_by === null) { + $model->create_by = $me->id; + } + if($model->edit_by === null) { + $model->edit_by = $me->id; + } + + return $model; + } + + public static function getAll() { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("PreordernotificationFile", "*", "1 = 1 ORDER BY preordernotification_id,file_id"); + if($db->num_rows($res)) { + while($data = $db->fetch_object($res)) { + $items[] = new PreordernotificationFile($data); + } + } + return $items; + + } + + public static function getFirst() { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("PreordernotificationFile", "*", "$where ORDER BY preordernotification_id,file_id LIMIT 1"); + if($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new PreordernotificationFile($data); + if($item->id) { + return $item; + } else { + return null; + } + } + return null; + } + + public static function count($filter) { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $sql = "SELECT COUNT(*) as cnt FROM `PreordernotificationFile` + WHERE $where + "; + + mfLoghandler::singleton()->debug($sql); + $res = $db->query($sql); + if($db->num_rows($res)) { + $data = $db->fetch_object($res); + return $data->cnt; + } + return 0; + } + + public static function search($filter, $limit=false) { + $items = []; + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + + $sql = "SELECT PreordernotificationFile.* FROM `PreordernotificationFile` + WHERE $where + ORDER BY preordernotification_id,file_id + "; + + mfLoghandler::singleton()->debug($sql); + if(is_array($limit) && count($limit)) { + if(is_numeric($limit['start']) && is_numeric($limit['count'])) { + $sql .= " LIMIT ".$limit['start'].", ".$limit['count']; + } elseif(is_numeric($count)) { + $sql .= " LIMIT ".$limit['count']; + } + } + + $res = $db->query($sql); + if($db->num_rows($res)) { + while($data = $db->fetch_object($res)) { + $items[] = new PreordernotificationFile($data); + } + } + return $items; + } + + private static function getSqlFilter($filter) { + $where = "1=1 "; + + $db = FronkDB::singleton(); + + //var_dump($filter);exit; + if(array_key_exists("id", $filter)) { + $id = $db->escape($filter['id']); + if($id) { + $where .= " AND PreordernotificationFile.`id` = '$id'"; + } + } + + if(array_key_exists("preordernotification_id", $filter)) { + $preordernotification_id = $filter['preordernotification_id']; + if(is_numeric($preordernotification_id)) { + $where .= " AND preordernotification_id=$preordernotification_id"; + } elseif(is_array($preordernotification_id) && count($preordernotification_id)) { + $where .= " AND PreordernotificationFile.preordernotification_id IN (". implode(",", $preordernotification_id).")"; + } + } + + + if(array_key_exists("file_id", $filter)) { + $file_id = $filter['file_id']; + if(is_numeric($file_id)) { + $where .= " AND PreordernotificationFile.file_id=$file_id"; + } elseif(is_array($file_id) && count($file_id)) { + $where .= " AND PreordernotificationFile.file_id IN (". implode(",", $file_id).")"; + } + } + + //var_dump($filter, $where);exit; + return $where; + } + +} \ No newline at end of file diff --git a/application/PreordernotificationLog/PreordernotificationLog.php b/application/PreordernotificationLog/PreordernotificationLog.php new file mode 100644 index 000000000..bc8c5a70f --- /dev/null +++ b/application/PreordernotificationLog/PreordernotificationLog.php @@ -0,0 +1,5 @@ + $value) { + if(property_exists(get_called_class(), $field)) { + $model ->$field = $value; + } + } + + $me = new User(); + $me->loadMe(); + + if($model->create_by === null) { + $model->create_by = $me->id; + } + if($model->edit_by === null) { + $model->edit_by = $me->id; + } + + return $model; + } + + public static function getAll() { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("PreordernotificationLog", "*", "1 = 1 ORDER BY `create`"); + if($db->num_rows($res)) { + while($data = $db->fetch_object($res)) { + $items[] = new PreordernotificationLog($data); + } + } + return $items; + + } + + public static function getFirst($filter) { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("PreordernotificationLog", "*", "$where ORDER BY `create` LIMIT 1"); + if($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new PreordernotificationLog($data); + if($item->id) { + return $item; + } else { + return null; + } + } + return null; + } + + public static function count($filter) { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $sql = "SELECT COUNT(*) as cnt FROM `PreordernotificationLog` + WHERE $where + "; + + mfLoghandler::singleton()->debug($sql); + $res = $db->query($sql); + if($db->num_rows($res)) { + $data = $db->fetch_object($res); + return $data->cnt; + } + return 0; + } + + public static function search($filter, $limit=false) { + $items = []; + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + + $sql = "SELECT PreordernotificationLog.* FROM `PreordernotificationLog` + WHERE $where + ORDER BY `create` + "; + + mfLoghandler::singleton()->debug($sql); + if(is_array($limit) && count($limit)) { + if(is_numeric($limit['start']) && is_numeric($limit['count'])) { + $sql .= " LIMIT ".$limit['start'].", ".$limit['count']; + } elseif(is_numeric($count)) { + $sql .= " LIMIT ".$limit['count']; + } + } + + $res = $db->query($sql); + if($db->num_rows($res)) { + while($data = $db->fetch_object($res)) { + $items[] = new PreordernotificationLog($data); + } + } + return $items; + } + + private static function getSqlFilter($filter) { + $where = "1=1 "; + + $db = FronkDB::singleton(); + + //var_dump($filter);exit; + if(array_key_exists("id", $filter)) { + $id = $filter['id']; + if(is_numeric($id)) { + $where .= " AND PreordernotificationLog.`id` = $id"; + } + } + + if(array_key_exists("preordernotification_id", $filter)) { + $preordernotification_id = $filter['preordernotification_id']; + if(is_numeric($preordernotification_id)) { + $where .= " AND preordernotification_id=$preordernotification_id"; + } elseif(is_array($preordernotification_id) && count($preordernotification_id)) { + $where .= " AND PreordernotificationLog.preordernotification_id IN (". implode(",", $preordernotification_id).")"; + } + } + + if(array_key_exists("preorder_id", $filter)) { + $preorder_id = $filter['preorder_id']; + if(is_numeric($preorder_id)) { + $where .= " AND preorder_id=$preorder_id"; + } elseif(is_array($preorder_id) && count($preorder_id)) { + $where .= " AND PreordernotificationLog.preorder_id IN (". implode(",", $preorder_id).")"; + } + } + + if(array_key_exists("email", $filter)) { + $email = $db->escape($filter['email']); + if($email) { + $where .= " AND PreordernotificationLog.email = '$email'"; + } + } + + + //var_dump($filter, $where);exit; + return $where; + } + +} \ No newline at end of file diff --git a/application/Preorderstatus/Preorderstatus.php b/application/Preorderstatus/Preorderstatus.php new file mode 100644 index 000000000..391d61669 --- /dev/null +++ b/application/Preorderstatus/Preorderstatus.php @@ -0,0 +1,16 @@ +id) { + return false; + } + + $a = []; + $a['code'] = (int)$this->code; + $a['text'] = $this->name; + + return $a; + } +} \ No newline at end of file diff --git a/application/Preorderstatus/PreorderstatusModel.php b/application/Preorderstatus/PreorderstatusModel.php new file mode 100644 index 000000000..40f2e81ed --- /dev/null +++ b/application/Preorderstatus/PreorderstatusModel.php @@ -0,0 +1,140 @@ + $value) { + if(property_exists(get_called_class(), $field)) { + if(substr($field, 0, 5) == "vlan_" && !$value) { + $model->$field = null; + continue; + } + $model->$field = $value; + } + } + + $me = mfValuecache::singleton()->get("me"); + if(!$me) { + $me = new User(); + $me->loadMe(); + mfValuecache::singleton()->set("me", $me); + } + + if($model->create_by === null) { + $model->create_by = $me->id; + } + if($model->edit_by === null) { + $model->edit_by = $me->id; + } + + return $model; + } + + + public static function getAll() { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("Preorderstatus", "*"); + if($db->num_rows($res)) { + while($data = $db->fetch_object($res)) { + $items[] = new Preorderstatus($data); + } + } + return $items; + + } + + public static function getFirst($filter = false) { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("Preorderstatus", "*", "$where ORDER BY code, name"); + if($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new Preorderstatus($data); + if($item->id) { + return $item; + } else { + return null; + } + } + return null; + } + + public static function count($filter) { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $sql = "SELECT COUNT(*) as cnt FROM Preorderstatus + WHERE $where + "; + + mfLoghandler::singleton()->debug($sql); + + $res = $db->query($sql); + if($db->num_rows($res)) { + $data = $db->fetch_object($res); + return $data->cnt; + } + return 0; + } + + public static function search($filter, $limit = false) { + $items = []; + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + + $sql = "SELECT * FROM Preorderstatus + WHERE $where + ORDER BY code, name + "; + + if(is_array($limit) && count($limit)) { + if(is_numeric($limit['start']) && is_numeric($limit['count'])) { + $sql .= " LIMIT ".$limit['start'].", ".$limit['count']; + } elseif(is_numeric($count)) { + $sql .= " LIMIT ".$limit['count']; + } + } + + mfLoghandler::singleton()->debug($sql); + + $res = $db->query($sql); + if($db->num_rows($res)) { + while($data = $db->fetch_object($res)) { + $items[] = new Preorderstatus($data); + } + } + return $items; + } + + private static function getSqlFilter($filter) { + $where = "1=1 "; + + //var_dump($filter);exit; + + if(array_key_exists("code", $filter)) { + $code = $filter['code']; + if(is_numeric($code)) { + $where .= " AND code=$code"; + } + } + + + //var_dump($filter, $where);exit; + return $where; + } + +} diff --git a/application/Product/Product.php b/application/Product/Product.php index 71779737c..4a87e12b5 100644 --- a/application/Product/Product.php +++ b/application/Product/Product.php @@ -9,7 +9,7 @@ class Product extends mfBaseModel { public function loadAttributes() { if(!$this->producttech_id) { - return false; + return []; } $this->attributes = []; diff --git a/application/Product/ProductController.php b/application/Product/ProductController.php index a6ca54caf..937c115f6 100644 --- a/application/Product/ProductController.php +++ b/application/Product/ProductController.php @@ -18,7 +18,48 @@ class ProductController extends mfBaseController { if(!$this->me->is(["Admin"])) { $this->redirect("Dashboard"); } - $this->layout()->set("products", ProductModel::getAll()); + + $filter = []; + if(is_array($this->request->filter)) { + $filter = $this->request->filter; + } + + $this->layout->set("filter", $filter); + + if($filter) { + $filter = $this->getPreparedFilter($filter); + } + + // pagination defaults + $pagination = []; + $pagination['start'] = 0; + $pagination['count'] = 20; + $pagination['maxItems'] = 0; + + if(is_numeric($this->request->s)) { + $pagination['start'] = intval($this->request->s); + } + + $pagination['maxItems'] = ProductModel::count($filter); + $this->layout()->set("pagination", $pagination); + + $products = ProductModel::search($filter, $pagination); + $this->layout()->set("products", $products); + } + + private function getPreparedFilter($filter) { + $new_filter = []; + + if(array_key_exists("name", $filter)) { + $new_filter['name%'] = $filter['name']; + unset($filter['name']); + } + + foreach($filter as $name => $value) { + $new_filter[$name] = $value; + } + + return $new_filter; } protected function addAction() { @@ -161,7 +202,7 @@ class ProductController extends mfBaseController { if($r->producttech_id == "new") { $nt = []; $nt['name'] = $r->producttech_new_name; - $nt['rtrcode'] = $r->producttech_new_rtrcode; + //$nt['rtrcode'] = $r->producttech_new_rtrcode; $nt['customer_type'] = ($r->producttech_new_customer_type == "business") ? "business" : "residential"; $nt['description'] = $r->producttech_new_description; $nt['note'] = $r->producttech_new_note; @@ -276,7 +317,7 @@ class ProductController extends mfBaseController { } - $products = array_merge($products, ProductModel::search(["nameLike" => $search])); + $products = array_merge($products, ProductModel::search(["name%" => $search])); if(!is_array($products) && !count($products)) { return false; diff --git a/application/Product/ProductModel.php b/application/Product/ProductModel.php index ad869f938..4def0073a 100644 --- a/application/Product/ProductModel.php +++ b/application/Product/ProductModel.php @@ -92,21 +92,55 @@ class ProductModel { return null; } - public static function search($filter) { + public static function count($filter) { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $sql = "SELECT COUNT(*) as cnt FROM ( + SELECT `Product`.id FROM `Product` + LEFT JOIN ProductAttribute ON (ProductAttribute.product_id = Product.id) + LEFT JOIN Producttech ON (Product.producttech_id = Producttech.id) + LEFT JOIN ProducttechAttribute ON (ProducttechAttribute.producttech_id = Producttech.id) + WHERE $where + GROUP BY Product.id + ) as p + "; + + mfLoghandler::singleton()->debug($sql); + $res = $db->query($sql); + if($db->num_rows($res)) { + $data = $db->fetch_object($res); + return $data->cnt; + } + return 0; + } + + public static function search($filter, $limit=false) { $items = []; $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); $sql = "SELECT Product.* FROM `Product` + LEFT JOIN Productgroup ON (Productgroup.id = Product.id) LEFT JOIN ProductAttribute ON (ProductAttribute.product_id = Product.id) LEFT JOIN Producttech ON (Product.producttech_id = Producttech.id) LEFT JOIN ProducttechAttribute ON (ProducttechAttribute.producttech_id = Producttech.id) WHERE $where - GROUP BY Product.id"; + GROUP BY Product.id + ORDER BY Productgroup.name,Producttech.name,Product.name + "; + + mfLoghandler::singleton()->debug($sql); + if(is_array($limit) && count($limit)) { + if(is_numeric($limit['start']) && is_numeric($limit['count'])) { + $sql .= " LIMIT ".$limit['start'].", ".$limit['count']; + } elseif(is_numeric($count)) { + $sql .= " LIMIT ".$limit['count']; + } + } $res = $db->query($sql); - //$res = $db->select("Product", "*", "$where ORDER BY name, producttech_id"); if($db->num_rows($res)) { while($data = $db->fetch_object($res)) { $items[] = new Product($data); @@ -124,7 +158,7 @@ class ProductModel { if(array_key_exists("id", $filter)) { $id = $db->escape($filter['id']); if($id) { - $where .= " AND Product.`id` like '%$id%'"; + $where .= " AND Product.`id` = '$id'"; } } @@ -132,13 +166,27 @@ class ProductModel { $productgroup_id = $filter['productgroup_id']; if(is_numeric($productgroup_id)) { $where .= " AND productgroup_id=$productgroup_id"; + } elseif(is_array($productgroup_id) && count($productgroup_id)) { + $where .= " AND Product.productgroup_id IN (". implode(",", $productgroup_id).")"; } } + if(array_key_exists("producttech_id", $filter)) { $producttech_id = $filter['producttech_id']; if(is_numeric($producttech_id)) { - $where .= " AND producttech_id=$producttech_id"; + $where .= " AND Product.producttech_id=$producttech_id"; + } elseif(is_array($producttech_id) && count($producttech_id)) { + $where .= " AND Product.producttech_id IN (". implode(",", $producttech_id).")"; + } + } + + if(array_key_exists("sla_id", $filter)) { + $sla_id = $filter['sla_id']; + if(is_numeric($sla_id)) { + $where .= " AND sla_id=$sla_id"; + } elseif(is_array($sla_id) && count($sla_id)) { + $where .= " AND Product.sla_id IN (". implode(",", $sla_id).")"; } } @@ -149,13 +197,32 @@ class ProductModel { } } - if(array_key_exists("nameLike", $filter)) { - $name = $db->escape($filter['nameLike']); + if(array_key_exists("name%", $filter)) { + $name = $db->escape($filter['name%']); if($name) { $where .= " AND Product.`name` like '%$name%'"; } } + if(array_key_exists("external", $filter)) { + $external = $filter['external']; + if(is_numeric($external)) { + if($external) { + $where .= " AND Product.external=1"; + } else { + $where .= " AND Product.external=0"; + } + } + } + + + if(array_key_exists("customer_type", $filter)) { + $customer_type = $db->escape($filter['customer_type']); + if($customer_type) { + $where .= " AND Producttech.`customer_type` = '$customer_type'"; + } + } + if(array_key_exists("attributename", $filter)) { $attributename = $db->escape($filter['attributename']); if($attributename) { diff --git a/application/Productgroup/Productgroup.php b/application/Productgroup/Productgroup.php index 7263f6835..1d569b5ea 100644 --- a/application/Productgroup/Productgroup.php +++ b/application/Productgroup/Productgroup.php @@ -1,5 +1,80 @@ $name == null) { + + if(!$this->id) { + return null; + } + + if($name == "products") { + $this->products = mfValuecache::singleton()->get("Productgroup-id-".$this->id."-Products"); + if($this->products === null) { + $this->products = ProductModel::search(['productgroup_id' => $this->id]); + if($this->products) { + mfValuecache::singleton()->set("Productgroup-id-".$this->id."-Products", $this->products); + } + } + return $this->products; + } + + if($name == "contractconfiggroups") { + $this->contractconfiggroups = mfValuecache::singleton()->get("Contractconfiggroups-byProductgroupid-".$this->id); + if($this->contractconfiggroups === null) { + $this->contractconfiggroups = []; + foreach(ContractconfiggroupProductgroupModel::search(['productgroup_id' => $this->id]) as $ccpg) { + $this->contractconfiggroups[$ccpg->contractconfiggroup_id] = $ccpg->contractconfiggroup; + } + if(count($this->contractconfiggroups)) { + mfValuecache::singleton()->set("Contractconfiggroups-byProductgroupid-".$this->id, $this->contractconfiggroups); + } + } + return $this->contractconfiggroups; + } + + if($name == "creator") { + $this->creator = mfValuecache::singleton()->get("Worker-id-".$this->create_by); + if($this->creator === null) { + $this->creator = new User($this->create_by); + if($this->creator->id) { + mfValuecache::singleton()->set("Worker-id-".$this->create_by, $this->creator); + } + } + return $this->creator; + } + + if($name == "editor") { + $this->editor = mfValuecache::singleton()->get("Worker-id-".$this->edit_by); + if($this->editor === null) { + $this->editor = new User($this->edit_by); + if($this->editor->id) { + mfValuecache::singleton()->set("Worker-id-".$this->edit_by, $this->editor); + } + } + return $this->editor; + } + + + $classname = ucfirst($name); + $idfield = $name."_id"; + $this->$name = mfValuecache::singleton()->get("mfObjectmodel-$name-".$this->$idfield); + if(!$this->$name) { + $this->$name = new $classname($this->$idfield); + } + + if($this->$name->id) { + mfValuecache::singleton()->set("mfObjectmodel-$name-".$this->$name->id, $this->$name); + return $this->$name; + } else { + return null; + } + + } + + return $this->$name; + } } \ No newline at end of file diff --git a/application/Productgroup/ProductgroupController.php b/application/Productgroup/ProductgroupController.php index 3d777b748..38a5cc812 100644 --- a/application/Productgroup/ProductgroupController.php +++ b/application/Productgroup/ProductgroupController.php @@ -15,15 +15,107 @@ class ProductgroupController extends mfBaseController { } protected function indexAction() { + $this->layout()->setTemplate("Productgroup/Index"); + $filter = []; + if(is_array($this->request->filter)) { + $filter = $this->request->filter; + } + + $this->layout->set("filter", $filter); + + if($filter) { + $filter = $this->getPreparedFilter($filter); + } + + // pagination defaults + $pagination = []; + $pagination['start'] = 0; + $pagination['count'] = 20; + $pagination['maxItems'] = 0; + + if(is_numeric($this->request->s)) { + $pagination['start'] = intval($this->request->s); + } + + $pagination['maxItems'] = ProductgroupModel::count($filter); + $this->layout()->set("pagination", $pagination); + $productgroups = ProductgroupModel::search($filter, $pagination); + $this->layout()->set("productgroups", $productgroups); } protected function addAction() { - + $this->layout()->setTemplate("Productgroup/Form"); } protected function editAction() { + $id = $this->request->id; + if(!is_numeric($id) || !$id) { + $this->layout()->setFlash("Produktgruppe nicht gefunden", "error"); + $this->redirect("Productgroup"); + } + $group = new Productgroup($id); + if(!$group->id) { + $this->layout()->setFlash("Produktgruppe nicht gefunden", "error"); + $this->redirect("Productgroup"); + } + + $this->layout()->set("group", $group); + + return $this->addAction(); + } + + protected function saveAction() { + $r = $this->request; + + $id = $r->id; + if(is_numeric($id) && $id > 0) { + $mode = "edit"; + $group = new Productgroup($id); + if(!$group->id) { + $this->layout()->setFlash("Produktgruppe nicht gefunden", "error"); + $this->redirect("Productgroup"); + } + } + + $name = trim($r->name); + if(!$name) { + $this->layout()->setFlash("Name darf nicht leer sein", "error"); + $this->redirect("Productgroup"); + } + + $group_data = []; + $group_data['name'] = $name; + + if($mode == "edit") { + $group->update($group_data); + } else { + $group = ProductgroupModel::create(['name' => $name]); + } + $id = $group->save(); + + if(!$id) { + $this->layout()->setFlash("Fehler beim Speichern", "error"); + $this->layout()->set("group", $group); + return $this->addAction(); + } + + // contractconfig groups + foreach(ContractconfiggroupProductgroupModel::search(['productgroup_id' => $id]) as $ccpg) { + $ccpg->delete(); + } + + foreach($r->contractconfiggroups as $cg_id) { + $ccgroup = ContractconfiggroupProductgroupModel::create([ + "productgroup_id" => $id, + "contractconfiggroup_id" => $cg_id + ]); + $ccgroup->save(); + } + + $this->layout()->setFlash("Produktgruppe erfolgreich gespeichert", "success"); + $this->redirect("Productgroup","edit", ['id' => $id]); } diff --git a/application/Productgroup/ProductgroupModel.php b/application/Productgroup/ProductgroupModel.php index 184d946f1..e418345d6 100644 --- a/application/Productgroup/ProductgroupModel.php +++ b/application/Productgroup/ProductgroupModel.php @@ -34,21 +34,6 @@ class ProductgroupModel { return $model; } - public static function getOne($id) { - if(!is_numeric($id) || !$id) { - throw new Exception("Invalid number", 400); - } - $item = []; - $db = FronkDB::singleton(); - - $res = $db->select("Productgroup", "*", "id=$id LIMIT 1"); - if($db->num_rows($res)) { - $data = $db->fetch_object($res); - $item = new Productgroup($data); - } - return $item; - } - public static function getAll() { $items = []; @@ -64,7 +49,7 @@ class ProductgroupModel { } - public static function getFirst() { + public static function getFirst($filter) { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); @@ -81,7 +66,23 @@ class ProductgroupModel { return null; } - public static function search($filter) { + public static function count($filter) { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $sql = "SELECT COUNT(*) as cnt FROM `Productgroup` + WHERE $where + "; + + $res = $db->query($sql); + if($db->num_rows($res)) { + $data = $db->fetch_object($res); + return $data->cnt; + } + return 0; + } + + public static function search($filter, $limit = false) { $items = []; $db = FronkDB::singleton(); diff --git a/application/Producttech/ProducttechModel.php b/application/Producttech/ProducttechModel.php index df2540111..9d758d169 100644 --- a/application/Producttech/ProducttechModel.php +++ b/application/Producttech/ProducttechModel.php @@ -2,7 +2,7 @@ class ProducttechModel { public $name = null; - public $rtrcode = null; + //public $rtrcode = null; public $customer_type = null; public $description = null; @@ -65,7 +65,7 @@ class ProducttechModel { } - public static function getFirst() { + public static function getFirst($filter) { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); diff --git a/application/ProducttechAttribute/ProducttechAttribute.php b/application/ProducttechAttribute/ProducttechAttribute.php index a5dafef73..9d21cfc6f 100644 --- a/application/ProducttechAttribute/ProducttechAttribute.php +++ b/application/ProducttechAttribute/ProducttechAttribute.php @@ -2,10 +2,30 @@ class ProducttechAttribute extends mfBaseModel { private $producttech; + private $contractval; + private $contract_id; + + + public function setContractId($contract_id) { + if(!is_numeric($contract_id)) { + return false; + } + $this->contract_id = $contract_id; + return true; + } public function getProperty($name) { if($this->$name == null) { + if($name == "contractval") { + if(!$this->contract_id) { + return null; + } + $this->contractval = ContractconfigValueModel::getFirst(['item_id' => $this->id]); + //var_dump($this->contractval); + return $this->contractval; + } + $classname = ucfirst($name); $idfield = $name."_id"; $this->$name = new $classname($this->$idfield); diff --git a/application/ProducttechAttribute/ProducttechAttributeModel.php b/application/ProducttechAttribute/ProducttechAttributeModel.php index 6f72c54a9..3f6773ae4 100644 --- a/application/ProducttechAttribute/ProducttechAttributeModel.php +++ b/application/ProducttechAttribute/ProducttechAttributeModel.php @@ -102,6 +102,20 @@ class ProducttechAttributeModel { $db = FronkDB::singleton(); + if(array_key_exists("forproduct", $filter)) { + $forproduct = $db->escape($filter['forproduct']); + if(is_numeric($forproduct)) { + $where .= " AND `forproduct` = $forproduct"; + } + } + + if(array_key_exists("forcontract", $filter)) { + $forcontract = $db->escape($filter['forcontract']); + if(is_numeric($forcontract)) { + $where .= " AND `forcontract` = $forcontract"; + } + } + //var_dump($filter);exit; if(array_key_exists("name", $filter)) { $name = $db->escape($filter['name']); diff --git a/application/User/User.php b/application/User/User.php index 3fc21192b..cfd9bf9df 100644 --- a/application/User/User.php +++ b/application/User/User.php @@ -185,7 +185,7 @@ class User extends mfBaseModel { } //var_dump($this->address->types);exit; if(is_object($this->address) && property_exists($this->address, "types") && is_array($this->address->types)) { - if($this->address->types[$w]->id) { + if(array_key_exists($w, $this->address->types) && $this->address->types[$w]->id) { return true; } } @@ -234,11 +234,13 @@ class User extends mfBaseModel { return $this->$name; } - public function myNetworks($type) { + public function myNetworks($types) { $typenets = []; $my_networks = $this->getProperty("my_networks"); - //var_dump($my_networks);exit; + if(!is_array($types)) { + $types = [$types]; + } foreach($my_networks as $net) { //var_dump($net);exit; @@ -246,10 +248,8 @@ class User extends mfBaseModel { if($this->address->parent_id) { $address_id = $this->address->parent_id; } - $found = NetworkaddressModel::search(['network_id' => $net->id, "addresstype" => [$type], 'address_id' => $address_id]); - //var_dump($found);exit; + $found = NetworkaddressModel::search(['network_id' => $net->id, "addresstype" => $types, 'address_id' => $address_id]); if($found) { - $this->log->debug("allowed net: ".$net->id); $typenets[] = $net; } diff --git a/lang/de.php b/lang/de.php index 87cdf1d1f..7cb6fb875 100644 --- a/lang/de.php +++ b/lang/de.php @@ -44,4 +44,10 @@ $l['preorder.provision'] = "Vorsorgeanschluss"; $l['preorder.order'] = "Vollanschluss"; $l['preorder.reorder'] = "Nachbestellung"; +$l['contract.link'] = "Verknüpfung"; +$l['contract.upgrade'] = "Upgrade"; +$l['contract.downgrade'] = "Downgrade"; +$l['contract.relocation'] = "Umzug"; +$l['contract.productchange'] = "Produktwechsel"; + $lang['de'] = $l; \ No newline at end of file diff --git a/lib/FronkDB/FronkDB.php b/lib/FronkDB/FronkDB.php index 0eabe60e7..9765a150f 100644 --- a/lib/FronkDB/FronkDB.php +++ b/lib/FronkDB/FronkDB.php @@ -34,9 +34,7 @@ class FronkDB { //echo "new FronkDB instance $instance_name\n"; $c = __CLASS__; self::$instances[$instance_name] = new $c($host,$user,$pass,$db); - } else { - //echo "existing FronkDB instance $instance_name\n"; - } + } return self::$instances[$instance_name]; } diff --git a/lib/Layout/Layout.php b/lib/Layout/Layout.php index 385128b59..69d4d2d7f 100644 --- a/lib/Layout/Layout.php +++ b/lib/Layout/Layout.php @@ -42,4 +42,17 @@ class Layout extends mfLayout { public static function intToDate($int) { return date("d.m.Y", $int); } + + /* + * Gets mfBaseModel object from Cache or gets in from DB and saves it to Cache + */ + public static function getMfValuecacheObject($objectname, $id) { + $object = mfValuecache::singleton()->get("mfObjectmodel-$objectname-".$id); + if(!$object) { + $object = new $objectname($id); + mfValuecache::singleton()->set("mfObjectmodel-$objectname-".$id, $object); + } + + return $object; + } } diff --git a/lib/mvcfronk/mfBase/mfBaseApicontroller.php b/lib/mvcfronk/mfBase/mfBaseApicontroller.php index 33f21a373..ab2f2aab0 100644 --- a/lib/mvcfronk/mfBase/mfBaseApicontroller.php +++ b/lib/mvcfronk/mfBase/mfBaseApicontroller.php @@ -42,6 +42,26 @@ class mfBaseApicontroller { $this->logRequest2(); register_shutdown_function(["mfBaseApicontroller", "return_errors"]); + + // CORS preflight + // allow all origins + if($this->http_method == "OPTIONS") { + // dont execute route, OPTIONS only requires CORS headers + header("Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS"); + header("Access-Control-Allow-Headers: X-Api-Key"); + + if(preg_match('#^(https?)://([^/:]+)(:\d+)?/?$#i', $this->headers['origin'], $m)) { + $origin_proto = $m[1]; + $origin_hostname = $m[2]; + $origin_port = $m[3]; + $allowed_origin = $origin_proto."://".$origin_hostname; + if($origin_port) { + $allowed_origin .= "$origin_port"; + } + header("Access-Control-Allow-Origin: $allowed_origin"); + $this->return(mfResponse::Ok()); + } + } // run Controllers init() function if(method_exists($this,"init")) { @@ -58,12 +78,6 @@ class mfBaseApicontroller { // Apicontroller should add allowed hostnames with $this->addAllowedOrigin() $this->createCorsHeaders(); - // CORS preflight OPTIONS - if($this->http_method == "OPTIONS") { - // dont execute route, OPTIONS only requires CORS headers - $this->return(mfResponse::Ok()); - } - // route to action $this->route = $params['apicall'].((array_key_exists("apiparams", $params)) ? $params['apiparams'] : ""); $responseData = $this->runRoute($this->route); @@ -114,6 +128,14 @@ class mfBaseApicontroller { $me->loadByApikey($key); if(!$me->id) { + header("Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS"); + header("Access-Control-Allow-Headers: X-Api-Key"); + + if(preg_match('#^(https?)://([^/:]+)(:\d+)?/?$#i', $this->headers['origin'], $m)) { + $origin_proto = $m[1]; + $origin_hostname = $m[2]; + header("Access-Control-Allow-Origin: ".$origin_proto."://".$origin_hostname); + } $this->return(mfResponse::Unauthorized(['message' => "API key missing or invalid"])); } $_SESSION[MFAPPNAME.'_username'] = $me->username; @@ -244,6 +266,8 @@ class mfBaseApicontroller { foreach($data as $key => $res) { if(is_array($res)) { $this->requestLog->debug($key.": (".count($res).")"); + } elseif(is_object($res)) { + $this->requestLog->debug($key.": object"); } else { $this->requestLog->debug($key.": ".$res); } @@ -301,9 +325,9 @@ class mfBaseApicontroller { } private function createCorsHeaders() { - header("Access-Control-Allow-Methods: GET,POST,OPTIONS"); + header("Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS"); header("Access-Control-Allow-Headers: X-Api-Key"); - //var_dump($this->headers);exit; + if(!is_array($this->allowed_origins) || !count($this->allowed_origins)) { return true; } @@ -314,14 +338,29 @@ class mfBaseApicontroller { return true; } - $request_origin = ["proto" => false, "hostname" => ""]; + $request_origin = ["proto" => false, "hostname" => "", "port" => false]; $m = []; - if(preg_match('#^(https?)://(.+)(:\d+)?$#i', $this->headers['origin'], $m)) { + if(preg_match('#^(https?)://([^/:]+)(:\d+)?/?$#i', $this->headers['origin'], $m)) { $request_origin['proto'] = $m[1]; $request_origin['hostname'] = $m[2]; + if(array_key_exists(3, $m) && $m[3]) { + $request_origin['port'] = $m[3]; + } + } else { + $this->return(mfResponse::Forbidden(["message" => "Malformed Origin header"])); + } + + if($request_origin['hostname'] == "localhost") { + // always allow requests from localhost + $this->log->debug("Allowing localhost Origin"); + $allowed_origin = $request_origin['proto']."://".$request_origin['hostname']; + if($request_origin['port']) { + $allowed_origin .= $request_origin['port']; + } + header("Access-Control-Allow-Origin: $allowed_origin"); + return true; } - //var_dump($request_origin);exit; foreach($this->allowed_origins as $origin) { //echo $origin." -> ".$_SERVER["HTTP_HOST"]; @@ -329,7 +368,7 @@ class mfBaseApicontroller { $hostname = $origin; $m = []; - if(preg_match('#^(https?)://(.+)$#i', $origin, $m)) { + if(preg_match('#^(https?)://([^/]+)/?$#i', $origin, $m)) { $proto = $m[1]; $hostname = $m[2]; } @@ -342,13 +381,22 @@ class mfBaseApicontroller { if(preg_match('/^'.$hostname.'$/', $request_origin['hostname'])) { if($proto) { if($proto == $request_origin['proto']) { - header("Access-Control-Allow-Origin: $proto://".$request_origin['hostname']); + $allowed_origin = $proto."://".$request_origin['hostname']; + if($request_origin['port']) { + $allowed_origin .= $request_origin['port']; + } + header("Access-Control-Allow-Origin: $allowed_origin"); return true; } } else { - header("Access-Control-Allow-Origin: ".$request_origin['proto']."://".$request_origin['hostname']); + $allowed_origin = $request_origin['proto']."://".$request_origin['hostname']; + if($request_origin['port']) { + $allowed_origin .= $request_origin['port']; + } + header("Access-Control-Allow-Origin: $allowed_origin"); return true; } + } } diff --git a/lib/mvcfronk/mfBase/mfBaseModel.php b/lib/mvcfronk/mfBase/mfBaseModel.php index 951e85d4f..9b118177b 100644 --- a/lib/mvcfronk/mfBase/mfBaseModel.php +++ b/lib/mvcfronk/mfBase/mfBaseModel.php @@ -16,13 +16,13 @@ class mfBaseModel { public $id; public $data; public $_old_data; - private $create; - private $edit; + protected $create; + protected $edit; private $worker; protected $forcestr; - private $mode = "new"; - private $saved = 0; + protected $mode = "new"; + protected $saved = 0; protected $db; protected $log; protected $table=false; @@ -223,6 +223,18 @@ class mfBaseModel { return "update"; } } + + public function startTransaction() { + $this->db->query("START TRANSACTION"); + } + + public function commitTransaction() { + $this->db->query("COMMIT"); + } + + public function rollbackTransaction() { + $this->db->query("ROLLBACK"); + } // generic functions for entity-classes public function toArray() { diff --git a/lib/mvcfronk/mfUpload/mfUpload.php b/lib/mvcfronk/mfUpload/mfUpload.php index b1a591a30..c9814d55f 100644 --- a/lib/mvcfronk/mfUpload/mfUpload.php +++ b/lib/mvcfronk/mfUpload/mfUpload.php @@ -46,6 +46,50 @@ class mfUpload { } } + public function getSavepath() { + return $this->savepath; + } + + public function setSavepath($path) { + $this->savepath = $path; + return true; + } + + public function getOriginalFilename() { + return $this->original_filename; + } + + public function getFilename() { + return $this->filename; + } + + public function setFilename($name) { + $this->filename = $name; + } + + public function getSize() { + return $this->size; + } + + public function getDirmode() { + return $this->dirmode; + } + + public function setDirmode($mode) { + $this->dirmode = $mode; + } + + public function getFilemode() { + return $this->filemode; + } + + public function setFilemode($mode) { + $this->filemode = $mode; + } + + public function getMimetype() { + return $this->upload->getMimetype(); + } public function save() { if(!$this->savepath) { @@ -95,7 +139,7 @@ class mfUpload { $string = ''; for ($p = 0; $p < $length; $p++) { - $string .= $characters[mt_rand(0, strlen($characters))]; + $string .= $characters[mt_rand(0, strlen($characters) -1)]; } $rand = uniqid(md5(rand()), true); @@ -133,44 +177,5 @@ class mfUpload { return true; } - public function getSavepath() { - return $this->savepath; - } - public function setSavepath($path) { - $this->savepath = $path; - return true; - } - - public function getOriginalFilename() { - return $this->original_filename; - } - - public function getFilename() { - return $this->filename; - } - - public function setFilename($name) { - $this->filename = $name; - } - - public function getSize() { - return $this->size; - } - - public function getDirmode() { - return $this->dirmode; - } - - public function setDirmode($mode) { - $this->dirmode = $mode; - } - - public function getFilemode() { - return $this->filemode; - } - - public function setFilemode($mode) { - $this->filemode = $mode; - } } diff --git a/lib/mvcfronk/mfUpload/mfUpload_TmpFile.php b/lib/mvcfronk/mfUpload/mfUpload_TmpFile.php index 547ae1012..d3c8045c9 100644 --- a/lib/mvcfronk/mfUpload/mfUpload_TmpFile.php +++ b/lib/mvcfronk/mfUpload/mfUpload_TmpFile.php @@ -13,15 +13,30 @@ class mfUpload_TmpFile { public function __construct($_file) { - $this->log = mfLoghandler::singleton(); + if(is_array($_file) && count($_file) == 2) { + $upload_name = $_file[0]; + $index = $_file[1]; + $upload = [ + 'name' => $_FILES[$upload_name]['name'][$index], + 'full_path' => $_FILES[$upload_name]['full_path'][$index], + 'type' => $_FILES[$upload_name]['type'][$index], + 'tmp_name' => $_FILES[$upload_name]['tmp_name'][$index], + 'error' => $_FILES[$upload_name]['error'][$index], + 'size' => $_FILES[$upload_name]['size'][$index], + ]; + } else { + $upload = $_FILES[$_file]; + } - if(count($_FILES[$_file])) { - $this->_file = $_FILES[$_file]; + if(count($upload)) { + $this->_file = $upload; } else { $this->errormessage = "Upload not found"; return false; } - + + + $this->filename = $this->_file['name']; $this->error = $this->_file['error']; $this->tmp_name = $this->_file['tmp_name']; @@ -81,7 +96,7 @@ class mfUpload_TmpFile { $ext = strtolower(array_pop($parts)); if(!preg_match('/^'.MFUPLOAD_ALLOWED_EXTENSIONS.'$/i',$ext)) { - $this->errormessage = "File type not allowed. Supported file types are ".ALLOWED_EXTENSIONS_STR; + $this->errormessage = "File type not allowed. Supported file types are ".MFUPLOAD_ALLOWED_EXTENSIONS_STR; return false; } diff --git a/lib/nusoap/changelog b/lib/nusoap/changelog deleted file mode 100644 index b76580e2d..000000000 --- a/lib/nusoap/changelog +++ /dev/null @@ -1,648 +0,0 @@ -2003-07-21, version 0.6.5 -- soap_transport_http: SOAPAction header is quoted again, fixes problem w/ Weblogic Server -- applied Jason Levitt patch for proper array serialization, fixes problem w/ Amazon shopping cart services -- fixed null value serialization -- applied patch from "BZC ToOn'S" - fixes wsdl serialization when no parameters -- applied John's patch, implementing compression for the server - -2003-07-22, version 0.6.5 -- soap_server: fixed bug causing charset encoding not to be passed to the parser -- soap_fault: added default encoding to the fault serialization -- soap_parser: changed the parser to pre-load the parent's result array when processing scalar values. This increases parsing speed. - -2003-07-23, version 0.6.5 -- soap_base: fix code that overwrites user-supplied attributes in serialize_val -- soap_base: use arrays-of-arrays rather than attempting multi-dimensional in serialize_val -- xmlschema: emit import statements and qualify all elements with prefix in serializeSchema (better interop with validation tools) -- soapclient: get xml character encoding from HTTP Content-Type header if provided, e.g. text/xml;charset="UTF-8" -- soapclient: use headers in call if provided (previously ignored this parameter) -- soap_server: in parse_request, if neither getallheaders nor $_SERVER are available, use $HTTP_SERVER_VARS to get SOAPAction and xml encoding - -2003-07-24, version 0.6.5 -- soap_transport_http: apply patch from Steven Brown "if the server closes connection prematurely, nusoap would spin trying to read data that isn't there" - -2003-07-25, version 0.6.5 -- wsdl: apply patch from Sven to workaround single schema limitation -- wsdl: apply a variant of the patch from Holger to handle empty values for array by serializing an array with 0 elements -- xmlschema: remove the redundant default namespace attribute on the schema element; everything in xsd is explicitly specified as being from xsd -- soap_transport_http: fix setCredentials and add TODO comments in sendHTTPS about what to change if this setCredentials stays - -2003-07-30, version 0.6.5 -- nusoap_base: change documentation of soap_defencoding to specify it is the encoding for outgoing messages -- nusoap_base: only change &, <, > to entities, not all HTML entities -- soap_transport_http: update the Content-Type header in sendRequest, since soap_defencoding could be changed after ctor is called -- soap_server: use soap_defencoding instead of charset_encoding -- soap_server: read encoding from _SERVER if available -- nusoap_base: do entity translation for string parameters with an xsd type specified (thanks David Derr) - -2003-07-31, version 0.6.5 -- soap_transport_http: add proxy authentication -- soap_transport_http: build payload the same way for http and https -- wsdl: add proxy authentication -- soapclient: add proxy authentication -- soapclient: allow proxy information in ctor, so that it can be used for wsdl - -2003-08-01, version 0.6.5 -- soap_transport_http: close a persistent connection that's at EOF -- soap_transport_http: prevent conflicts between setEncoding and usePersistentConnection -- soap_transport_http: fix use of $headers instead of $this->incoming_headers in getResponse -- soapclient: improve handling of persistent connections -- soapclient: force xml_encoding to upper case -- soap_server: let the Web server decide whether to close the connection (no Connection: close header) -- soap_server: force xml_encoding to upper case - -2003-08-04, version 0.6.5 -- soap_parser: use XML type information to pick a PHP data type; also decode base64 -- soap_server: read all HTTP headers when using _SERVER or HTTP_SERVER_VARS -- soap_server: add gzip encoding support for outgoing messages -- soap_transport_http: deflate is gzcompress/gzuncompress (cf. http://archive.develooper.com/libwww@perl.org/msg04650.html) -- soap_transport_http: clean use of persistentConnection so it's always a set boolean -- soapclient: add responseData member to access deflated/gunzipped payload - -2003-08-05, version 0.6.5 -- soap_server: look multiple places when setting debug_flag - -2003-08-07, version 0.6.5 -- nusoap_base: serialize specified type (e.g. ArrayOfString) even for simple array -- wsdl: only specify encodingStyle in the input/output soap bindings when it is not empty (thanks Guillaume) - -2003-08-15, version 0.6.5 -- soap_parser: fix parsing of elements with no XSD type specified -- soap_parser: use PHP string type for XSD long and unsignedLong types - -2003-08-16, version 0.6.5 -- soap_parser: fix code generating warning (thanks Torsten) - -2003-08-19, version 0.6.5 -- soap_parser: fix another line of code generating a warning (thanks Torsten) - -2003-08-22, version 0.6.5 -- soap_server: remove all '--' from debug_str; previous code changed '---' to '- --' -- wsdl, soapclient, soap_parser: patch submitted by Mark Spavin as described by - the following... -> Changes for the multiple/nested imports from the wsdl file. This builds an -> array of files not just the last one and also checks for relative paths to -> the parent. This will then get the imported files from the remote site -> instead of your local disk. Local wsdl files should still work (untested). -> -> Changes for multiple encoding sytles as previously posted - -2003-08-24, version 0.6.5 -- wsdl, soapclient: fix some PHP notices from previous update - -2003-08-26, version 0.6.5 -- wsdl: support multiple SOAP ports -- soapclient, soap_server: when no charset is specified, use UTF-8, even though HTTP specifies US-ASCII. -- soap_transport_http: do not prepend $host with 'ssl://' for https (is this required for older cURL versions?) - -2003-08-27, version 0.6.5 -- soap_server: support compressed request messages (thanks John Huong) -- soap_parser: deserialize Apache Vector as an array -- xmlschema: use $this->typemap in getPHPType (which is not used) -- soapclient, wsdl: check for WSDL errors after serializing parameters -- nusoap_base: add serialization of Apache Map (when not using WSDL) -- wsdl: add serialization of Apache Map (when using WSDL) -- wsdl: only change &, <, > to entities, not all HTML entities - -2003-08-28, version 0.6.5 -- soap_transport_http: disable cURL verification of peer and server (formerly the cURL default) -- soap_transport_http: mingle cURL code with straight http, so sendHTTP is no longer needed - -2003-08-29, version 0.6.6 -- soap_transport_http: add setContentType -- soapclient: call setContentType using new getHTTPContentType and getHTTPContentTypeCharset - -2003-09-05, version 0.6.6 -- wsdl: add some more code to handle null/nil values (but there's still a way to go) - -2003-10-21, version 0.6.6 -- soap_transport_http: only include port in Host header if it was specified in the URL -- soap_transport_http: add some code to use OpenSSL for PHP ssl:// scheme, but comment out since it's not ready -- soap_server: use $_SERVER['PHP_SELF'] if $GLOBALS['PHP_SELF'] is not set -- wsdl: add WSDL request and response and transport debug to debug -- wsdl: handle custom type extending xmlschema namespace (GLUE ... Thanks Matt) -- soap_parser: add param to docs -- soapclient: add getHTTPBody, getHTTPContentType, getHTTPContentTypeCharset (anticipating MIME subclass) - -2003-10-28, version 0.6.6 -- nusoap_base: add expandEntities method -- wsdl: use expandEntities -- soap_fault: use expandEntities -- soap_transport_http: Allow credentials to be included in URL, rather than requiring setCredentials -- soap_transport_http: Merge HTTP headers that span multiple lines -- soap_parser: Properly set errors in ctor -- soapclient: Pass headers to parseResponse and parse them in that method - -2003-10-30, version 0.6.6 -- xmlschema: Add some information for the related type to an element - -2003-12-09, version 0.6.6 -- nusoap_base: Add some namespace methods previously in xmlschema -- xmlschema: Improve parsing of complexType, element and simpleType -- xmlschema: Improve serialization -- xmlschema: Track imports -- xmlschema: Track elementFormDefault and form attributes -- wsdl: Support multiple (note that setting $server->wsdl->schemaTargetNamespace no longer does anything! Use configureWSDL instead.) -- wsdl: Use form attribute of element to control namespace specification -- wsdl: Support chained imports (A imports B which imports C) -- wsdl: Include port in endpoint address when serializing -- soap_server: Fix use of style (rpc|document) and use (encoded|literal) -- soap_server: Support _SERVER[CONTENT_TYPE] in addition to _SERVER[HTTP_CONTENT_TYPE] -- soap_server: Support wsdl with multiple -- soap_client: Remove a var_dump -- soap_client: Add style and use parameters to call method to support doc/lit without WSDL -- soap_transport_http: Check that $this->fp exists when doing persistent connections - -2003-12-17, version 0.6.6 -- soap_server: pass namespaces to xmlschema constructor -- wsdl: post-process after all imports -- wsdl: remove some debug, add some error handling -- xmlschema: allow enclosing namespaces to be specified in constructor -- xmlschema: improve handling of compositors and simple types - -2004-01-08, version 0.6.6 -- soap_server: when requested WSDL is in a file, return to client using passthru (thanks Ingo Fischer) -- soapclient: have proxy inherit more client state -- soapclient: allow timeout and response timeout to be specified in the constructor -- wsdl: allow timeout and response timeout to be specified in the constructor -- soap_transport_http: allow response timeout to be specified in send and sendHTTPS - -2004-01-28, version 0.6.6 -- wsdl: add namespace for array and scalar when form is qualified -- wsdl: fix a bug in which data type of complexType elements were ignored in serialization -- wsdl: enhance handling of URLs with file scheme -- wsdl: add addSimpleType -- xmlschema: add addSimpleType -- xmlschema: always set phpType elements -- soapclient: allow a wsdl instance to be specified in constructor -- soap_server: allow a wsdl instance to be specified in constructor (not tested!) -- soap_server: fix default SOAPAction created in register method -- soap_transport_http: accept chunking with LF separators in addition to CRLF. -- wsdlcache: added class -- nusoapmime: fix comments - -2004-02-23, version 0.6.6 -- soap_transport_http: don't try to unchunk cURL data, since cURL already does it -- soap_transport_http: append CVS revision to version in User-Agent -- wsdl: serialize boolean as true|false, not 1|0, to agree with XML Schema -- soap_server: always exit() after returning WSDL -- soap_server: use the WSDL URL scheme as the default endpoint URL scheme -- soap_server: append CVS revision to version in X-SOAP-Server -- nusoap_base: add (CVS) revision -- wsdlcache: synchronize using a per-WSDL lock file (Thanks Ingo) -- wsdlcache: add cache lifetime, after which cache contents are invalidated (Thanks Ingo) - -2004-03-15, version 0.6.6 -- nusoap_base: add isArraySimpleOrStruct method -- soap_server: improve WSDL URL scheme determination -- soap_server: only deflate/gzip payloads > 1024 bytes -- soap_server: fix parameter order in fault method (always used as faultcode, faultstring) -- soap_server: refactor parse_request into multiple functions (for sanity) -- soap_server: set the namespace on the Response element to the same as the request -- soap_server: name the return value element 'return' by default -- soap_server: added and documented data fields, so that service programmers can use them if desired -- soap_parser: standardize parsing error message -- soap_parser: fix document and responseHeaders so they are the correct XML text (as documented) -- soap_transport_http: fix read from persistent connection -- soapclient: clean up debugging for persistent connection -- wsdl: enforce correct naming of messages parts when an associative array is used for parameters -- wsdl: better serialization of null values -- wsdl: standardize parsing error message -- xmlschema: standardize parsing error message - -2004-03-24, version 0.6.7 -- soap_transport_http: add digest authentication (based on code by Kevin A. Miller) -- xmlschema: improve parsing of import elements -- wsdl: do schema imports even if there are no wsdl imports - -2004-04-12, version 0.6.7 -- wsdl: serialize multiple elements when maxOccurs="unbounded" and value is an array -- wsdl: serialize soapval values (used to force an XML type, e.g. when WSDL uses an abstract type) -- nusoapmime: do not require nusoap.php (it is now the programmer's responsibility) - -2004-04-21, version 0.6.7 -- soap_parser: parse repeated element name into an array (de-serializes doc/lit array into a PHP array when there is more than 1 array element) -- soap_server: do not wrap response in a response element for a document style service - -2004-04-30, version 0.6.7 -- soap_transport_http: allow digest auth params to be separated by "," as well as ", " -- soap_transport_http: re-initialize incoming headers for each response -- soap_server: add methodreturnisliteralxml property to allow service function to return XML as a string -- soapclient: improve rpc/literal support -- soapclient: allow XML string as call params in addition to array -- soapclient: support document style and literal encoding when not using WSDL - -2004-05-05, version 0.6.7 -- wsdl: serialize PHP objects for WSDL XML Schema complexTypes, in addition to associative arrays -- wsdl: fix WSDL generation when there is no encodingStyle -- soap_transport_http: suppress fsockopen warnings -- soap_transport_http: detect socket timeouts when reading (0 bytes returned) -- soap_transport_http: read chunked content "in-line" so it works on a persistent connection -- nusoap_base: serialize boolean as true|false, not 1|0, to agree with XML Schema -- nusoap_base: serialize array of struct differently than array of array - -2004-06-25, version 0.6.8 -- soap_server: prefer gzip to deflate, since IE does not like our deflate -- soap_server: move webDescription to the wsdl class -- soap_server: allow class and instance method calls for service (thanks Ingo Fischer and Roland Knall) -- wsdl: get webDescription from the soap_server class -- wsdl: allow compression from the server -- wsdl: fix serialization of soapval without a type -- wsdl: propagate debug value from query string to SOAP endpoint in programmatic WSDL generation -- nusoap_base: add anyType, anySimpleType for 2001 XML Schema -- nusoap_base: provide additional debug functions -- soap_transport_http: ignore Content-Length when chunked encoding is used -- soap_transport_http: remove ':' from username for Basic authentication (cf. RFC 2617) -- soap_transport_http: urldecode username and password taken from URL -- soap_transport_http: use raw inflate/deflate for IE/IIS compatibility, rather than having Zlib headers according to HTTP 1.1 spec -- soap_transport_http: attempt to handle the case when both the service application and Web server compress the response -- soapclient: when creating proxy methods, replace '.' in operation name with '__' in function name -- soapclient: initialize requestHeaders in proxy -- general: use new debug methods; never access debug_str directly - -2004-09-30, version 0.6.8 -- soapclient: do not allow getProxy call when WSDL is not used -- soapclient: use ISO-8859-1 as the charset if not specified in the Content-Type header -- soapclient: when an empty string is specified for the call namespace, do not put the method element in a namespace -- soapclient: let soap_transport_http check for SSL support -- soapclient: have proxy inherit soap_defencoding from the client from which it is generated -- soapclient: do not assume that 'ns1' is an unused namespace prefix; always generate namespace prefixes randomly -- soap_parser: compare any encoding in the XML declaration to the charset from the HTTP Content-Type header (thanks Ingo Fischer) -- soap_parser: improve parse repeated element name into an array (de-serializes doc/lit array into a PHP array when there is more than 1 array element) -- soap_server: use ISO-8859-1 as the charset if not specified in the Content-Type header -- soap_server: allow suppression of automatic UTF-8 decoding -- soap_server: fix a bug when call_user_func_array() is used -- soap_transport_http: correct digest authentication through a proxy -- wsdl: serialize SOAP-ENC types similarly to XSD types -- xmlschema: force unprefixed type into default namespace -- xmlschema: fix serialization of definition of simple types - -2004-10-01, version 0.6.8 -- soap_parser: handle default namespace attributes -- soap_server: add default_utf8 field -- soap_server: support literal encoding (with RPC style) -- soap_transport_http: parse HTTP status and generate error for 300, 302-307, 400, 401-417, 501-505 (thanks for the idea Ghislain) -- soap_transport_http: follow HTTP redirection (HTTP status 301 and Location header) (thanks for the idea Ghislain) -- xmlschema: allow any attributes to be specified in an element of a complexType, e.g., abstract, default, form, minOccurs, maxOccurs, nillable (thanks Jirka Pech for the original patch) - -2004-10-02, version 0.6.8 -- soapclient: read/write cookies (thanks Ingo) -- soap_server: change faultcode on non-resendable faults to Client -- soap_transport_http: read/write cookies (thanks Ingo) - -2004-10-05, version 0.6.8 -- wsdl: add addElement method -- wsdl: support the document style in the register method -- xmlschema: parse unnamed simpleTypes, rather than ignoring them -- xmlschema: include untyped elements when parsing a complexType -- xmlschema: add addElement method - -2004-10-14, version 0.6.8 -- soapclient: support client certificates -- soap_parser: deserialize attributes, prefixing names with "!" -- soap_server: notify the client with HTML when WSDL is requested but not supported by service -- soap_transport_http: support client certificates -- wsdl: support defaults for elements of a complexType -- wsdl: serialize elements from complexType extension base -- wsdl: serialize data (associative array elements) as attributes according to XML Schema -- xmlschema: record extension base if present for a complexType - -2004-12-15, version 0.6.8 -- nusoap_base: add 2000 XML Schema (rare, but used by Akamai) -- soap_parser: avoid deserializing more common attributes that are not data -- soap_parser: be lax when HTTP specifies ISO-8859-1 (the default) and XML specifies UTF-8 (the norm) -- soap_server: account for the fact that get_class_methods returns methods in all lower case (thanks Steve Haldane) -- soap_transport_http: parse digest info that includes '=' in the data (thanks Jinsuk Kim) -- wsdl: feably handle some cases for literal serialization of form="unqualified" elements -- wsdl: don't serialize the decimal portion of a PHP double when the XML type is long -- wsdl: fix serialization of attributes for complexType that is an extension -- wsdlcache: enhance diagnostics -- xmlschema: handle untyped elements -- xmlschema: handle WSDL for SOAP Array that uses the base attribute plus a sequence of element - -2005-01-22, version 0.6.8 -- wsdl: allow an element in one schema to have a type from another schema - -2005-01-24, version 0.6.8 -- xmlschema: correctly parse nested complexType definitions - -2005-02-14, version 0.6.8 -- nusoap_base: fix a bug in which attributes were sometimes not serialized with a value -- nusoap_base: improve serialization of null values (thanks Dominique Stender) -- soap_parser: parse null values by handling the nil attribute (thanks Dominique Stender) -- soap_server: set character encoding for a fault to be the same as for the server (thanks Mark Scott) -- soap_server: correctly check for null value returned from method when WSDL is used (without WSDL, cannot distinguish whether NULL or void return is desired) -- soapclient: for document style, call should always return an array rooted at the response part (all bets are off when there are multiple parts) -- xmlschema: save enumeration values parsed from WSDL - -2005-02-10, version 0.6.9 -- soapclient: only set SOAP headers when they are specified in call params (so setHeaders still works) - -2005-04-04, version 0.6.9 -- soap_server: use get_class instead of is_a (thanks Thomas Noel) -- soapclient: use get_class instead of is_a (thanks Thomas Noel) -- soapclient: add setEndpoint method -- soap_transport_http: fix client certificates (thanks Doug Anarino and Eryan Eriobowo) - -2005-04-29, version 0.6.9 -- nusoap_base: add global variable and methods for setting debug level -- nusoap_base: use xsd:anyType instead of xsd:ur-type to serialize arrays with multiple element types (thanks Ingo Fischer) -- nusoap_base: expand entities in attributes (thanks Gaetano Giunta) -- soapclient: call parent constructor -- soapval: call parent constructor -- soap_fault: call parent constructor -- soap_parser: call parent constructor -- soap_server: assume get_class_methods always returns lower case for PHP 4.x only -- soap_server: call parent constructor -- soap_transport_http: do nothing in setEncoding if gzdeflate is not present (thanks Franck Touanen for pointing this out) -- soap_transport_http: fix check for server request for digest authentication (thanks Mark Spavin) -- soap_transport_http: call parent constructor -- wsdl: fix documentation page popup of one method after another (thanks Owen) -- wsdl: call parent constructor -- wsdl: expand entities in attributes (thanks Gaetano Giunta) -- xmlschema: call parent constructor - -2005-06-03, version 0.6.9 -- nusoap_base: serialize empty arrays as having elements xsd:anyType[0] -- nusoap_base: add encodingStyle parameter to serializeEnvelope -- nusoap_base: serialize xsi:type with nil values -- nusoap_base: improve debug and comments -- soap_parser: correctly parse an empty array to an empty array, not an empty string -- soap_parser: improve debug and comments -- soap_server: specify encodingStyle for envelope when WSDL is used -- soapclient: factor out new getProxyClassCode method -- soapclient: specify encodingStyle for envelope -- soapclient: improve debug and comments -- wsdl: add namespace for Apache SOAP types if a variable of such type is serialized -- wsdl: serialize nil value for nillable elements when no value is provided -- wsdl: serialize xsi:type with nil values -- wsdl: copy attributes as well as elements to an element from its complexType -- wsdl: specify encodingStyle for operations -- wsdl: improve debug and comments -- xmlschema: improve debug and comments - -2005-06-03, version 0.7.0 -- nusoap_base: improve debug and comments -- nusoap_base: fix version, which should have been 0.7.0 since 2005-03-04 - -2005-06-06, version 0.7.1 -- nusoap_base: adjust numeric element names for serialization, instead of forcing them to 'soapVal' -- nusoapmime: add type=text/xml to multipart/related (thanks Emmanuel Cordonnier) -- soap_fault: fix serialization of detail -- soap_server: check required parameters for register method -- soap_server: when getallheaders is used, massage header names -- soap_server: use SOAPAction to determine operation when doc/lit service does not wrap parameters in an element with the method name (thanks Peter Hrastnik) -- soap_transport_http: correctly handle multiple HTTP/1.1 100 responses for https (thanks Jan Slabon) -- wsdl: fixed documentation for addComplexType (thanks Csintalan dm) -- wsdl: serialize array data when maxOccurs = 'unbounded' OR maxOccurs > 1 (thanks Dominique Schreckling) -- wsdl: when serializing a string == 'false' as a boolean, set the value to false -- wsdl: when serializing a complexType, require the PHP value supplied to be an array - -2005-07-01, version 0.7.1 -- nusoap_base: Allow SOAP headers to be supplied as an array like parameters -- soap_parser: de-serialize simpleContent that accompanies complexContent -- soap_server: append debug information when programmatically-defined WSDL is returned -- soap_transport_http: Add debug when an outgoing header is set -- soapclient: Allow SOAP headers to be supplied as an array like parameters -- xmlschema: serialize attributes more generally, rather than assuming they are for SOAP 1.1 Array -- wsdl: when serializing, look up types by namespace, not prefix (simple programmatic doc/lit WSDL now seems to work) -- wsdl: process namespace declarations first when parsing an element - -2005-07-27, version 0.7.1 -- nusoap_base: do not override supplied element name with class name when serializing an object in serialize_val -- nusoap_base: remove http://soapinterop.org/xsd (si) from namespaces array -- nusoapmime: add nusoapservermime class to implement MIME attachments on the server -- soap_fault: improve documentation -- soap_server: improve documentation -- soap_server: make consistent use of _SERVER and HTTP_SERVER_VARS -- soap_server: make all incoming HTTP header keys lower case -- soap_server: add hook functions to support subclassing for MIME attachments -- soap_transport_http: remove an unnecessary global statement -- soapclient: when creating a proxy, make $params within each function an associative array -- soapval: improve documentation -- wsdl: when serializing complexType elements, used typed serialization if there is either a type or a reference for the element -- wsdl: allow PHP objects to be serialized as SOAP structs in serializeType -- wsdl: for WSDL and XML Schema imports, don't forget to use the TCP port number (thanks Luca GIOPPO) -- wsdl: make consistent use of _SERVER and HTTP_SERVER_VARS -- xmlschema: improve documentation - -2005-07-31, version 0.7.2 -- nusoap_base: correctly serialize attributes in serialize_val (thanks Hidran Arias) -- soap_parser: when resolving references, do not assume that buildVal returns an array (thanks Akshell) -- soap_parser: removed decode_entities, which does not work (thanks Martin Sarsale) -- soap_server: fix a bug parsing headers from _SERVER and HTTP_SERVER_VARS (thanks Bert Catsburg) -- soap_server: parse all "headers" from HTTP_SERVER_VARS (not just HTTP_*) -- soap_server: use PHP_SELF instead of SCRIPT_NAME for WSDL endpoint -- soap_server: when generating a fault while debug_flag is true, put debug into faultdetail -- wsdl: add enumeration parameter to addSimpleType -- xmlschema: add enumeration parameter to addSimpleType - -2006-02-02, version 0.7.2 -- soapclient: initialize paramArrayStr to improve proxy generation -- soap_parser: handle PHP5 soapclient's incorrect transmission of WSDL-described SOAP encoded arrays. -- soap_server: don't assume _SERVER['HTTPS'] is set; try HTTP_SERVER_VARS['HTTPS'] if it is not -- soap_server: "flatten out" the parameter array to call_user_func_array (thanks Andr Mamitzsch) -- soap_server: make thrown exceptions conform to specs -- wsdl: use serialize_val to serialize an array when the XSD type is soapenc:Array (JBoss/Axis does this) -- wsdl: change formatting of serialized XML for the WSDL -- xmlschema: change formatting of namespaces when serializing XML for the schema - -2006-04-07, version 0.7.2 -- soap_server: if methodparams is not an array, call call_user_func_array with an empty array (thanks Eric Grossi) -- wsdl: distinguish parts with element specified from those with type specified by suffixing element names with ^ -- wsdl: do a case-insensitive match on schema URI when looking for type -- xmlschema: only get element (not type) when name has ^ suffix - -2006-05-16, version 0.7.2 -- soapclient: add getHeader to get parsed SOAP Header -- soap_parser: check status when receiving Header or Body element -- soap_parser: add soapheader -- soap_server: add requestHeader with parsed SOAP Header - -2006-06-15, version 0.7.2 -- wsdl: fix bug in addComplexType (thanks Maarten Meijer) -- soap_transport_http: change cURL message - -2007-03-19, version 0.7.2 -- soapclient: declare as nusoapclient, then also subclass soapclient if SOAP extension not loaded -- soapclientmime: declare as nusoapclientmime, then also subclass soapclientmime if SOAP extension not loaded - -2007-03-28, version 0.7.2 -- nusoap_base: fix serialization of a soapval when its value is a soapval -- soapval: fix serialization of a soapval when its value is a soapval -- soapval: add __toString (cf. http://article.gmane.org/gmane.comp.php.nusoap.general/2776) -- nusoapclient: use lazy retrieval of WSDL instead of always getting it in the constructor -- nusoapclient: fix getProxy that was broken in last revision -- wsdl: add ability to set authorization credentials and retrieve WSDL outside of constructor - -2007-04-05, version 0.7.2 -- nusoapclientmime: don't rely exclusively on Content-Disposition to distinguish the root part from attachment; also check Content-Type (thanks Ben Bosman) -- nusoapclientmime: obey RFC 2045 Section 5.1 (thanks Chris Butler) -- nusoapservermime: don't rely exclusively on Content-Disposition to distinguish the root part from attachment; also check Content-Type (thanks Ben Bosman) -- nusoapservermime: obey RFC 2045 Section 5.1 (thanks Chris Butler) -- nusoap_base: remove extra whitespace from some XML elements -- nusoap_base: allow SOAP headers to be specified as an associative array (thanks Unique) -- nusoap_base: implement __toString -- nusoap_base: improve doc accuracy and consistency (thanks Martin K?gler) -- iso8601_to_timestamp: avoid problem with negative hours after calculation, etc. (thanks Guntram Trebs) -- nusoapclient: support user-settable cURL options (thanks Ciprian Popovici) -- nusoapclient: call SOAP 1.2 binding operations if no SOAP 1.1 present (there is no reason to believe this will always work!) -- nusoapclient: improve doc accuracy and consistency (thanks Martin K?gler) -- soap_server: don't try to use eval to call function when any parameter is an object -- soap_server: don't print return value within debug string; returned objects would need __toString in PHP 5.2 -- soap_server: use URL scheme for WSDL access as the scheme in SOAPAction -- soap_server: strip port number from server name (some FastCGI implementations include port in server name) -- soap_transport_http: support user-settable cURL options (thanks Ciprian Popovici) -- soap_transport_http: use cURL for NTLM authentication -- soap_transport_http: make digest authentication work for GET as well as POST -- soap_transport_http: improve doc accuracy and consistency (thanks Martin K?gler) -- soapval: remove __toString -- wsdl: set operation style if necessary, but do not override one already provided (thanks Raffaele Capobianco) -- wsdl: check SOAP 1.2 binding operations if no SOAP 1.1 present -- wsdl: improve doc accuracy and consistency (thanks Martin K?gler) -- xmlschema: fix simpleType serialization -- xmlschema: improve doc accuracy and consistency (thanks Martin K?gler) - -2007-04-09, version 0.7.2 -- nusoapclient: set decode_utf8 when creating a proxy (thanks Dmitri Dmitrienko) -- nusoapclient: rename class to nusoap_client -- soap_fault: also provide a class named nusoap_fault -- soap_parser: also provide a class named nusoap_parser -- soap_server: also provide a class named nusoap_server -- soap_transport_http: skip HTTP responses 301 and 401 when using cURL -- soap_transport_http: don't force HTTP Connection header when using cURL -- soap_transport_http: don't set HTTP Host and Content-Length headers when using cURL -- soap_transport_http: support CURLOPT_SSLCERTPASSWD (thanks David Blanco) -- wsdl: support user-settable cURL options (thanks Ciprian Popovici) -- wsdl: serialize parameters for non-SOAP 1.1 binding operations (there is no reason to believe this will always work!) -- xmlschema: also provide a class named nusoap_xmlschema -- nusoapclientmime: rename class to nusoap_client_mime -- nusoapservermime: rename class to nusoap_server_mime - -2007-04-11, version 0.7.2 -- nusoap_client: enable cURL usage to be forced (thanks Giunta Gaetano) -- soap_transport_http: enable cURL proxy usage (thanks Giunta Gaetano) -- soap_transport_http: enable cURL usage to be forced (thanks Giunta Gaetano) -- soap_transport_http: use cURL's HTTP authentication options for basic, digest -- wsdl: enable cURL usage to be forced (thanks Giunta Gaetano) - -2007-04-12, version 0.7.2 -- nusoap_client: add debug -- nusoap_xmlschema: don't add elements of complexTypes to elements array (thanks Heiko Hund) -- soap_transport_http: set cURL connection timeout if supported -- soap_transport_http: add debug when setting cURL option -- soap_transport_http: fix digest authentication broken in previous revision -- wsdl: add debug -- wsdlcache: address some issues with non-existing cache-files and PHP Warnings which came in such cases (thanks Ingo Fischer) -- wsdlcache: change class name to nusoap_wsdlcache - -2007-04-13, version 0.7.2 -- wsdl: wrap parameters if unwrapped values are supplied and WSDL specifies Microsoft-style wrapping - -2007-04-16, version 0.7.2 -- nusoap_base: avoid warning in getDebugAsXMLComment -- nusoap_client: small debug change -- nusoap_client_mime: set responseData when the root part is found - -2007-04-17, version 0.7.2 -- soap_transport_http: improve detection of undefined cURL options (thanks Ingo Fischer) - -2007-05-28, version 0.7.2 -- soap_transport_http: support digest authentication opaque feature (cf. RFC 2617) (thanks Daniel Lacroix) -- soap_transport_http: check safe_mode and open_basedir before setting CURLOPT_FOLLOWLOCATION -- soap_transport_http: skip "HTTP/1.0 200 Connection established" header when cURL returns it (thanks Raimund Jacob) -- nusoap_client: improve handling when getProxy is called and WSDL is not being used -- nusoap_base: add comments about which specifications are used/implemented by NuSOAP -- nusoap_xmlschema: create names for unnamed types that are unique by scope within XML Schema - -2007-06-11, version 0.7.2 -- wsdl: wrap return value if unwrapped value is supplied and WSDL specifies Microsoft-style wrapping - -2007-06-22, version 0.7.2 -- nusoap_xmlschema: fix serialization of simpleType restriction (thanks Rizwan Tejpar) - -2007-07-30, version 0.7.2 -- nusoap_server: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras) -- nusoap_client: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras) - -2007-10-21, version 0.7.2 -- nusoap_server: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras) -- nusoap_client: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras) - -2007-10-26, version 0.7.2 -- nusoap_server: Fix munging of _SERVER variables that start with HTTP_ (thanks Thomas Wieczorek) - -2007-10-30, version 0.7.2 -- nusoap_xmlschema: Serialize values for elementFormDefault, attributeFormDefault -- wsdl: Improve consistency between doc/lit schema auto-wrapping and client's parsed schema -- nusoap_server: Correct bug that placed encodingType in Envelope for doc/lit -- nusoap_server: Specify elementFormDefault for schema within doc/lit wsdl - -2007-10-31, version 0.7.2 -- wsdl: Fix typo in parametersMatchWrapped (thanks Sam Stepanyan) -- soap_transport_http: Fix three typos in setProxy (thanks Sam Stepanyan) -- nusoap_xmlschema: Fix typo in serializeTypeDef (thanks Sam Stepanyan) - -2007-11-06, version 1.0rc1 -- wsdl: Improve handling of return values from doc/lit methods -- nusoap_server: Handle case when method is not in a namespace - -2007-11-27, version 1.0rc1 -- nusoap_server: always try to invoke service for a POST -- nusoap_server: only return Location: for WSDL at http://... -- nusoap_base: change some syntax associated with globalDebugLevel - -2008-01-08, version 1.0rc1 -- nusoap_server: fix a typo where = was used instead of == (thanks J. (Johan) Bosma) - -2008-01-10, version 1.0rc1 -- nusoap_client: handle case where request or response has no content-type header (thanks Ingo Fischer) -- nusoap_server: handle case where request or response has no content-type header (thanks Ingo Fischer) -- wsdl: change CSS for .title in webDescription (thanks Marcus Uy) - -2008-01-25, version 1.0rc1 -- nusoap_xmlschema: when an element is of a complexType that is an extension, copy extensionBase from the type -- nusoap_xmlschema: do not apply elementFormDefault to globally defined elements - -2008-02-11, version 1.0rc1 -- wsdl: internally set form of wrapped parameter elements to unqualified (so server handles correctly) - -2008-03-03, version 1.0.rc1 -- nusoap_xmlschema: fix extension when base type has no explicit prefix -- nusoap_xmlschema: support XML Schema include -- wsdl: improve support for sequence by serializing inherited attributes and elements first - -2008-03-04, version 1.0.rc1 -- wsdl: allow WSDL port name to be specified in getOperations -- nusoap_client: allow WSDL port name to be specified in ctor - -2008-03-06, version 1.0rc1 -- wsdl: fix some port name variable references -- nusoap_base: change comments regarding preferred mode of support -- wsdl2nusoap: initial revision - -2008-03-14, version 1.0rc1 -- nusoap_base: fix timezone offset in timestamp_to_iso8601 (thanks Mario Trojan) - -2008-03-27, version 1.0rc1 -- nusoap_server: fix bug setting encodingStyle in serialize_return (thanks Luca Gobbo) - -2008-05-15, version 1.0rc1 -- nusoap_parser: handle case where Header or Body tags are used within SOAP messages (thanks Sergey Zhuravlev) - -2008-08-26, version 1.0rc1 -- wsdl: serialize simpleContent for complexType -- wsdl: avoid serializing complexType elements with no value and minOccurs = 0 regardless of nillability - -2010-04-26, version 0.9.5 -- nusoap_xmlschema: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine) -- wsdl: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine) -- soap_transport_http: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine) -- soap_transport_http: remove call to deprecated function set_magic_quotes_runtime -- nusoap_server: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine) -- nusoap_server: check that value is an object before calling get_class (thanks Pier-Luc Duchaine) -- nusoap_parser: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine) -- nusoap_client: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine) -- nusoap_client: do not assign the return value of new by reference (it is deprecated) (thanks Pier-Luc Duchaine) -- nusoap_base: replace regex function calls (ereg, eregi, split) with PCRE calls (preg_match, preg_split) (thanks Pier-Luc Duchaine) -- nusoapmime: do not assign the return value of new by reference (it is deprecated) diff --git a/lib/nusoap/class.nusoap_base.php b/lib/nusoap/class.nusoap_base.php deleted file mode 100644 index 4ed92a751..000000000 --- a/lib/nusoap/class.nusoap_base.php +++ /dev/null @@ -1,996 +0,0 @@ - -* @author Scott Nichol -* @version $Id: class.nusoap_base.php,v 1.56 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_base { - /** - * Identification for HTTP headers. - * - * @var string - * @access private - */ - var $title = 'NuSOAP'; - /** - * Version for HTTP headers. - * - * @var string - * @access private - */ - var $version = '0.9.5'; - /** - * CVS revision for HTTP headers. - * - * @var string - * @access private - */ - var $revision = '$Revision: 1.56 $'; - /** - * Current error string (manipulated by getError/setError) - * - * @var string - * @access private - */ - var $error_str = ''; - /** - * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment) - * - * @var string - * @access private - */ - var $debug_str = ''; - /** - * toggles automatic encoding of special characters as entities - * (should always be true, I think) - * - * @var boolean - * @access private - */ - var $charencoding = true; - /** - * the debug level for this instance - * - * @var integer - * @access private - */ - var $debugLevel; - - /** - * set schema version - * - * @var string - * @access public - */ - var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema'; - - /** - * charset encoding for outgoing messages - * - * @var string - * @access public - */ - var $soap_defencoding = 'ISO-8859-1'; - //var $soap_defencoding = 'UTF-8'; - - /** - * namespaces in an array of prefix => uri - * - * this is "seeded" by a set of constants, but it may be altered by code - * - * @var array - * @access public - */ - var $namespaces = array( - 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/', - 'xsd' => 'http://www.w3.org/2001/XMLSchema', - 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance', - 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/' - ); - - /** - * namespaces used in the current context, e.g. during serialization - * - * @var array - * @access private - */ - var $usedNamespaces = array(); - - /** - * XML Schema types in an array of uri => (array of xml type => php type) - * is this legacy yet? - * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings. - * @var array - * @access public - */ - var $typemap = array( - 'http://www.w3.org/2001/XMLSchema' => array( - 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double', - 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'', - 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string', - // abstract "any" types - 'anyType'=>'string','anySimpleType'=>'string', - // derived datatypes - 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'', - 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer', - 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer', - 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''), - 'http://www.w3.org/2000/10/XMLSchema' => array( - 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double', - 'float'=>'double','dateTime'=>'string', - 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'), - 'http://www.w3.org/1999/XMLSchema' => array( - 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double', - 'float'=>'double','dateTime'=>'string', - 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'), - 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'), - 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'), - 'http://xml.apache.org/xml-soap' => array('Map') - ); - - /** - * XML entities to convert - * - * @var array - * @access public - * @deprecated - * @see expandEntities - */ - var $xmlEntities = array('quot' => '"','amp' => '&', - 'lt' => '<','gt' => '>','apos' => "'"); - - /** - * constructor - * - * @access public - */ - function nusoap_base() { - $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel']; - } - - /** - * gets the global debug level, which applies to future instances - * - * @return integer Debug level 0-9, where 0 turns off - * @access public - */ - function getGlobalDebugLevel() { - return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel']; - } - - /** - * sets the global debug level, which applies to future instances - * - * @param int $level Debug level 0-9, where 0 turns off - * @access public - */ - function setGlobalDebugLevel($level) { - $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level; - } - - /** - * gets the debug level for this instance - * - * @return int Debug level 0-9, where 0 turns off - * @access public - */ - function getDebugLevel() { - return $this->debugLevel; - } - - /** - * sets the debug level for this instance - * - * @param int $level Debug level 0-9, where 0 turns off - * @access public - */ - function setDebugLevel($level) { - $this->debugLevel = $level; - } - - /** - * adds debug data to the instance debug string with formatting - * - * @param string $string debug data - * @access private - */ - function debug($string){ - if ($this->debugLevel > 0) { - $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n"); - } - } - - /** - * adds debug data to the instance debug string without formatting - * - * @param string $string debug data - * @access public - */ - function appendDebug($string){ - if ($this->debugLevel > 0) { - // it would be nice to use a memory stream here to use - // memory more efficiently - $this->debug_str .= $string; - } - } - - /** - * clears the current debug data for this instance - * - * @access public - */ - function clearDebug() { - // it would be nice to use a memory stream here to use - // memory more efficiently - $this->debug_str = ''; - } - - /** - * gets the current debug data for this instance - * - * @return debug data - * @access public - */ - function &getDebug() { - // it would be nice to use a memory stream here to use - // memory more efficiently - return $this->debug_str; - } - - /** - * gets the current debug data for this instance as an XML comment - * this may change the contents of the debug data - * - * @return debug data as an XML comment - * @access public - */ - function &getDebugAsXMLComment() { - // it would be nice to use a memory stream here to use - // memory more efficiently - while (strpos($this->debug_str, '--')) { - $this->debug_str = str_replace('--', '- -', $this->debug_str); - } - $ret = ""; - return $ret; - } - - /** - * expands entities, e.g. changes '<' to '<'. - * - * @param string $val The string in which to expand entities. - * @access private - */ - function expandEntities($val) { - if ($this->charencoding) { - $val = str_replace('&', '&', $val); - $val = str_replace("'", ''', $val); - $val = str_replace('"', '"', $val); - $val = str_replace('<', '<', $val); - $val = str_replace('>', '>', $val); - } - return $val; - } - - /** - * returns error string if present - * - * @return mixed error string or false - * @access public - */ - function getError(){ - if($this->error_str != ''){ - return $this->error_str; - } - return false; - } - - /** - * sets error string - * - * @return boolean $string error string - * @access private - */ - function setError($str){ - $this->error_str = $str; - } - - /** - * detect if array is a simple array or a struct (associative array) - * - * @param mixed $val The PHP array - * @return string (arraySimple|arrayStruct) - * @access private - */ - function isArraySimpleOrStruct($val) { - $keyList = array_keys($val); - foreach ($keyList as $keyListValue) { - if (!is_int($keyListValue)) { - return 'arrayStruct'; - } - } - return 'arraySimple'; - } - - /** - * serializes PHP values in accordance w/ section 5. Type information is - * not serialized if $use == 'literal'. - * - * @param mixed $val The value to serialize - * @param string $name The name (local part) of the XML element - * @param string $type The XML schema type (local part) for the element - * @param string $name_ns The namespace for the name of the XML element - * @param string $type_ns The namespace for the type of the element - * @param array $attributes The attributes to serialize as name=>value pairs - * @param string $use The WSDL "use" (encoded|literal) - * @param boolean $soapval Whether this is called from soapval. - * @return string The serialized element, possibly with child elements - * @access public - */ - function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) { - $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval"); - $this->appendDebug('value=' . $this->varDump($val)); - $this->appendDebug('attributes=' . $this->varDump($attributes)); - - if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) { - $this->debug("serialize_val: serialize soapval"); - $xml = $val->serialize($use); - $this->appendDebug($val->getDebug()); - $val->clearDebug(); - $this->debug("serialize_val of soapval returning $xml"); - return $xml; - } - // force valid name if necessary - if (is_numeric($name)) { - $name = '__numeric_' . $name; - } elseif (! $name) { - $name = 'noname'; - } - // if name has ns, add ns prefix to name - $xmlns = ''; - if($name_ns){ - $prefix = 'nu'.rand(1000,9999); - $name = $prefix.':'.$name; - $xmlns .= " xmlns:$prefix=\"$name_ns\""; - } - // if type is prefixed, create type prefix - if($type_ns != '' && $type_ns == $this->namespaces['xsd']){ - // need to fix this. shouldn't default to xsd if no ns specified - // w/o checking against typemap - $type_prefix = 'xsd'; - } elseif($type_ns){ - $type_prefix = 'ns'.rand(1000,9999); - $xmlns .= " xmlns:$type_prefix=\"$type_ns\""; - } - // serialize attributes if present - $atts = ''; - if($attributes){ - foreach($attributes as $k => $v){ - $atts .= " $k=\"".$this->expandEntities($v).'"'; - } - } - // serialize null value - if (is_null($val)) { - $this->debug("serialize_val: serialize null"); - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$name$xmlns$atts/>"; - $this->debug("serialize_val returning $xml"); - return $xml; - } else { - if (isset($type) && isset($type_prefix)) { - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ''; - } - $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>"; - $this->debug("serialize_val returning $xml"); - return $xml; - } - } - // serialize if an xsd built-in primitive type - if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){ - $this->debug("serialize_val: serialize xsd built-in primitive type"); - if (is_bool($val)) { - if ($type == 'boolean') { - $val = $val ? 'true' : 'false'; - } elseif (! $val) { - $val = 0; - } - } else if (is_string($val)) { - $val = $this->expandEntities($val); - } - if ($use == 'literal') { - $xml = "<$name$xmlns$atts>$val"; - $this->debug("serialize_val returning $xml"); - return $xml; - } else { - $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val"; - $this->debug("serialize_val returning $xml"); - return $xml; - } - } - // detect type and serialize - $xml = ''; - switch(true) { - case (is_bool($val) || $type == 'boolean'): - $this->debug("serialize_val: serialize boolean"); - if ($type == 'boolean') { - $val = $val ? 'true' : 'false'; - } elseif (! $val) { - $val = 0; - } - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val"; - } - break; - case (is_int($val) || is_long($val) || $type == 'int'): - $this->debug("serialize_val: serialize int"); - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val"; - } - break; - case (is_float($val)|| is_double($val) || $type == 'float'): - $this->debug("serialize_val: serialize float"); - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val"; - } - break; - case (is_string($val) || $type == 'string'): - $this->debug("serialize_val: serialize string"); - $val = $this->expandEntities($val); - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val"; - } - break; - case is_object($val): - $this->debug("serialize_val: serialize object"); - if (get_class($val) == 'soapval') { - $this->debug("serialize_val: serialize soapval object"); - $pXml = $val->serialize($use); - $this->appendDebug($val->getDebug()); - $val->clearDebug(); - } else { - if (! $name) { - $name = get_class($val); - $this->debug("In serialize_val, used class name $name as element name"); - } else { - $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val)); - } - foreach(get_object_vars($val) as $k => $v){ - $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use); - } - } - if(isset($type) && isset($type_prefix)){ - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ''; - } - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$pXml"; - } else { - $xml .= "<$name$xmlns$type_str$atts>$pXml"; - } - break; - break; - case (is_array($val) || $type): - // detect if struct or array - $valueType = $this->isArraySimpleOrStruct($val); - if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){ - $this->debug("serialize_val: serialize array"); - $i = 0; - if(is_array($val) && count($val)> 0){ - foreach($val as $v){ - if(is_object($v) && get_class($v) == 'soapval'){ - $tt_ns = $v->type_ns; - $tt = $v->type; - } elseif (is_array($v)) { - $tt = $this->isArraySimpleOrStruct($v); - } else { - $tt = gettype($v); - } - $array_types[$tt] = 1; - // TODO: for literal, the name should be $name - $xml .= $this->serialize_val($v,'item',false,false,false,false,$use); - ++$i; - } - if(count($array_types) > 1){ - $array_typename = 'xsd:anyType'; - } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) { - if ($tt == 'integer') { - $tt = 'int'; - } - $array_typename = 'xsd:'.$tt; - } elseif(isset($tt) && $tt == 'arraySimple'){ - $array_typename = 'SOAP-ENC:Array'; - } elseif(isset($tt) && $tt == 'arrayStruct'){ - $array_typename = 'unnamed_struct_use_soapval'; - } else { - // if type is prefixed, create type prefix - if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){ - $array_typename = 'xsd:' . $tt; - } elseif ($tt_ns) { - $tt_prefix = 'ns' . rand(1000, 9999); - $array_typename = "$tt_prefix:$tt"; - $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\""; - } else { - $array_typename = $tt; - } - } - $array_type = $i; - if ($use == 'literal') { - $type_str = ''; - } else if (isset($type) && isset($type_prefix)) { - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\""; - } - // empty array - } else { - if ($use == 'literal') { - $type_str = ''; - } else if (isset($type) && isset($type_prefix)) { - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\""; - } - } - // TODO: for array in literal, there is no wrapper here - $xml = "<$name$xmlns$type_str$atts>".$xml.""; - } else { - // got a struct - $this->debug("serialize_val: serialize struct"); - if(isset($type) && isset($type_prefix)){ - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ''; - } - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>"; - } else { - $xml .= "<$name$xmlns$type_str$atts>"; - } - foreach($val as $k => $v){ - // Apache Map - if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') { - $xml .= ''; - $xml .= $this->serialize_val($k,'key',false,false,false,false,$use); - $xml .= $this->serialize_val($v,'value',false,false,false,false,$use); - $xml .= ''; - } else { - $xml .= $this->serialize_val($v,$k,false,false,false,false,$use); - } - } - $xml .= ""; - } - break; - default: - $this->debug("serialize_val: serialize unknown"); - $xml .= 'not detected, got '.gettype($val).' for '.$val; - break; - } - $this->debug("serialize_val returning $xml"); - return $xml; - } - - /** - * serializes a message - * - * @param string $body the XML of the SOAP body - * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array - * @param array $namespaces optional the namespaces used in generating the body and headers - * @param string $style optional (rpc|document) - * @param string $use optional (encoded|literal) - * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) - * @return string the message - * @access public - */ - function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){ - // TODO: add an option to automatically run utf8_encode on $body and $headers - // if $this->soap_defencoding is UTF-8. Not doing this automatically allows - // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1 - - $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle"); - $this->debug("headers:"); - $this->appendDebug($this->varDump($headers)); - $this->debug("namespaces:"); - $this->appendDebug($this->varDump($namespaces)); - - // serialize namespaces - $ns_string = ''; - foreach(array_merge($this->namespaces,$namespaces) as $k => $v){ - $ns_string .= " xmlns:$k=\"$v\""; - } - if($encodingStyle) { - $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string"; - } - - // serialize headers - if($headers){ - if (is_array($headers)) { - $xml = ''; - foreach ($headers as $k => $v) { - if (is_object($v) && get_class($v) == 'soapval') { - $xml .= $this->serialize_val($v, false, false, false, false, false, $use); - } else { - $xml .= $this->serialize_val($v, $k, false, false, false, false, $use); - } - } - $headers = $xml; - $this->debug("In serializeEnvelope, serialized array of headers to $headers"); - } - $headers = "".$headers.""; - } - // serialize envelope - return - 'soap_defencoding .'"?'.">". - '". - $headers. - "". - $body. - "". - ""; - } - - /** - * formats a string to be inserted into an HTML stream - * - * @param string $str The string to format - * @return string The formatted string - * @access public - * @deprecated - */ - function formatDump($str){ - $str = htmlspecialchars($str); - return nl2br($str); - } - - /** - * contracts (changes namespace to prefix) a qualified name - * - * @param string $qname qname - * @return string contracted qname - * @access private - */ - function contractQname($qname){ - // get element namespace - //$this->xdebug("Contract $qname"); - if (strrpos($qname, ':')) { - // get unqualified name - $name = substr($qname, strrpos($qname, ':') + 1); - // get ns - $ns = substr($qname, 0, strrpos($qname, ':')); - $p = $this->getPrefixFromNamespace($ns); - if ($p) { - return $p . ':' . $name; - } - return $qname; - } else { - return $qname; - } - } - - /** - * expands (changes prefix to namespace) a qualified name - * - * @param string $qname qname - * @return string expanded qname - * @access private - */ - function expandQname($qname){ - // get element prefix - if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){ - // get unqualified name - $name = substr(strstr($qname,':'),1); - // get ns prefix - $prefix = substr($qname,0,strpos($qname,':')); - if(isset($this->namespaces[$prefix])){ - return $this->namespaces[$prefix].':'.$name; - } else { - return $qname; - } - } else { - return $qname; - } - } - - /** - * returns the local part of a prefixed string - * returns the original string, if not prefixed - * - * @param string $str The prefixed string - * @return string The local part - * @access public - */ - function getLocalPart($str){ - if($sstr = strrchr($str,':')){ - // get unqualified name - return substr( $sstr, 1 ); - } else { - return $str; - } - } - - /** - * returns the prefix part of a prefixed string - * returns false, if not prefixed - * - * @param string $str The prefixed string - * @return mixed The prefix or false if there is no prefix - * @access public - */ - function getPrefix($str){ - if($pos = strrpos($str,':')){ - // get prefix - return substr($str,0,$pos); - } - return false; - } - - /** - * pass it a prefix, it returns a namespace - * - * @param string $prefix The prefix - * @return mixed The namespace, false if no namespace has the specified prefix - * @access public - */ - function getNamespaceFromPrefix($prefix){ - if (isset($this->namespaces[$prefix])) { - return $this->namespaces[$prefix]; - } - //$this->setError("No namespace registered for prefix '$prefix'"); - return false; - } - - /** - * returns the prefix for a given namespace (or prefix) - * or false if no prefixes registered for the given namespace - * - * @param string $ns The namespace - * @return mixed The prefix, false if the namespace has no prefixes - * @access public - */ - function getPrefixFromNamespace($ns) { - foreach ($this->namespaces as $p => $n) { - if ($ns == $n || $ns == $p) { - $this->usedNamespaces[$p] = $n; - return $p; - } - } - return false; - } - - /** - * returns the time in ODBC canonical form with microseconds - * - * @return string The time in ODBC canonical form with microseconds - * @access public - */ - function getmicrotime() { - if (function_exists('gettimeofday')) { - $tod = gettimeofday(); - $sec = $tod['sec']; - $usec = $tod['usec']; - } else { - $sec = time(); - $usec = 0; - } - return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec); - } - - /** - * Returns a string with the output of var_dump - * - * @param mixed $data The variable to var_dump - * @return string The output of var_dump - * @access public - */ - function varDump($data) { - ob_start(); - var_dump($data); - $ret_val = ob_get_contents(); - ob_end_clean(); - return $ret_val; - } - - /** - * represents the object as a string - * - * @return string - * @access public - */ - function __toString() { - return $this->varDump($this); - } -} - -// XML Schema Datatype Helper Functions - -//xsd:dateTime helpers - -/** -* convert unix timestamp to ISO 8601 compliant date string -* -* @param int $timestamp Unix time stamp -* @param boolean $utc Whether the time stamp is UTC or local -* @return mixed ISO 8601 date string or false -* @access public -*/ -function timestamp_to_iso8601($timestamp,$utc=true){ - $datestr = date('Y-m-d\TH:i:sO',$timestamp); - $pos = strrpos($datestr, "+"); - if ($pos === FALSE) { - $pos = strrpos($datestr, "-"); - } - if ($pos !== FALSE) { - if (strlen($datestr) == $pos + 5) { - $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2); - } - } - if($utc){ - $pattern = '/'. - '([0-9]{4})-'. // centuries & years CCYY- - '([0-9]{2})-'. // months MM- - '([0-9]{2})'. // days DD - 'T'. // separator T - '([0-9]{2}):'. // hours hh: - '([0-9]{2}):'. // minutes mm: - '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss... - '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's - '/'; - - if(preg_match($pattern,$datestr,$regs)){ - return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]); - } - return false; - } else { - return $datestr; - } -} - -/** -* convert ISO 8601 compliant date string to unix timestamp -* -* @param string $datestr ISO 8601 compliant date string -* @return mixed Unix timestamp (int) or false -* @access public -*/ -function iso8601_to_timestamp($datestr){ - $pattern = '/'. - '([0-9]{4})-'. // centuries & years CCYY- - '([0-9]{2})-'. // months MM- - '([0-9]{2})'. // days DD - 'T'. // separator T - '([0-9]{2}):'. // hours hh: - '([0-9]{2}):'. // minutes mm: - '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss... - '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's - '/'; - if(preg_match($pattern,$datestr,$regs)){ - // not utc - if($regs[8] != 'Z'){ - $op = substr($regs[8],0,1); - $h = substr($regs[8],1,2); - $m = substr($regs[8],strlen($regs[8])-2,2); - if($op == '-'){ - $regs[4] = $regs[4] + $h; - $regs[5] = $regs[5] + $m; - } elseif($op == '+'){ - $regs[4] = $regs[4] - $h; - $regs[5] = $regs[5] - $m; - } - } - return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); -// return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z"); - } else { - return false; - } -} - -/** -* sleeps some number of microseconds -* -* @param string $usec the number of microseconds to sleep -* @access public -* @deprecated -*/ -function usleepWindows($usec) -{ - $start = gettimeofday(); - - do - { - $stop = gettimeofday(); - $timePassed = 1000000 * ($stop['sec'] - $start['sec']) - + $stop['usec'] - $start['usec']; - } - while ($timePassed < $usec); -} - - -?> \ No newline at end of file diff --git a/lib/nusoap/class.soap_fault.php b/lib/nusoap/class.soap_fault.php deleted file mode 100644 index 1515b5035..000000000 --- a/lib/nusoap/class.soap_fault.php +++ /dev/null @@ -1,90 +0,0 @@ - -* @version $Id: class.soap_fault.php,v 1.14 2007/04/11 15:49:47 snichol Exp $ -* @access public -*/ -class nusoap_fault extends nusoap_base { - /** - * The fault code (client|server) - * @var string - * @access private - */ - var $faultcode; - /** - * The fault actor - * @var string - * @access private - */ - var $faultactor; - /** - * The fault string, a description of the fault - * @var string - * @access private - */ - var $faultstring; - /** - * The fault detail, typically a string or array of string - * @var mixed - * @access private - */ - var $faultdetail; - - /** - * constructor - * - * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server) - * @param string $faultactor only used when msg routed between multiple actors - * @param string $faultstring human readable error message - * @param mixed $faultdetail detail, typically a string or array of string - */ - function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){ - parent::nusoap_base(); - $this->faultcode = $faultcode; - $this->faultactor = $faultactor; - $this->faultstring = $faultstring; - $this->faultdetail = $faultdetail; - } - - /** - * serialize a fault - * - * @return string The serialization of the fault instance. - * @access public - */ - function serialize(){ - $ns_string = ''; - foreach($this->namespaces as $k => $v){ - $ns_string .= "\n xmlns:$k=\"$v\""; - } - $return_msg = - 'soap_defencoding.'"?>'. - '\n". - ''. - ''. - $this->serialize_val($this->faultcode, 'faultcode'). - $this->serialize_val($this->faultactor, 'faultactor'). - $this->serialize_val($this->faultstring, 'faultstring'). - $this->serialize_val($this->faultdetail, 'detail'). - ''. - ''. - ''; - return $return_msg; - } -} - -/** - * Backward compatibility - */ -class soap_fault extends nusoap_fault { -} - - -?> \ No newline at end of file diff --git a/lib/nusoap/class.soap_parser.php b/lib/nusoap/class.soap_parser.php deleted file mode 100644 index f6932aa26..000000000 --- a/lib/nusoap/class.soap_parser.php +++ /dev/null @@ -1,643 +0,0 @@ - -* @author Scott Nichol -* @version $Id: class.soap_parser.php,v 1.42 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_parser extends nusoap_base { - - var $xml = ''; - var $xml_encoding = ''; - var $method = ''; - var $root_struct = ''; - var $root_struct_name = ''; - var $root_struct_namespace = ''; - var $root_header = ''; - var $document = ''; // incoming SOAP body (text) - // determines where in the message we are (envelope,header,body,method) - var $status = ''; - var $position = 0; - var $depth = 0; - var $default_namespace = ''; - var $namespaces = array(); - var $message = array(); - var $parent = ''; - var $fault = false; - var $fault_code = ''; - var $fault_str = ''; - var $fault_detail = ''; - var $depth_array = array(); - var $debug_flag = true; - var $soapresponse = NULL; // parsed SOAP Body - var $soapheader = NULL; // parsed SOAP Header - var $responseHeaders = ''; // incoming SOAP headers (text) - var $body_position = 0; - // for multiref parsing: - // array of id => pos - var $ids = array(); - // array of id => hrefs => pos - var $multirefs = array(); - // toggle for auto-decoding element content - var $decode_utf8 = true; - - /** - * constructor that actually does the parsing - * - * @param string $xml SOAP message - * @param string $encoding character encoding scheme of message - * @param string $method method for which XML is parsed (unused?) - * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1 - * @access public - */ - function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){ - parent::nusoap_base(); - $this->xml = $xml; - $this->xml_encoding = $encoding; - $this->method = $method; - $this->decode_utf8 = $decode_utf8; - - // Check whether content has been read. - if(!empty($xml)){ - // Check XML encoding - $pos_xml = strpos($xml, '', $pos_xml + 2) - $pos_xml + 1); - if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) { - $xml_encoding = $res[1]; - if (strtoupper($xml_encoding) != $encoding) { - $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'"; - $this->debug($err); - if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') { - $this->setError($err); - return; - } - // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed - } else { - $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration'); - } - } else { - $this->debug('No encoding specified in XML declaration'); - } - } else { - $this->debug('No XML declaration'); - } - $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding); - // Create an XML parser - why not xml_parser_create_ns? - $this->parser = xml_parser_create($this->xml_encoding); - // Set the options for parsing the XML data. - //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); - xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); - xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding); - // Set the object for the parser. - xml_set_object($this->parser, $this); - // Set the element handlers for the parser. - xml_set_element_handler($this->parser, 'start_element','end_element'); - xml_set_character_data_handler($this->parser,'character_data'); - - // Parse the XML file. - if(!xml_parse($this->parser,$xml,true)){ - // Display an error message. - $err = sprintf('XML error parsing SOAP payload on line %d: %s', - xml_get_current_line_number($this->parser), - xml_error_string(xml_get_error_code($this->parser))); - $this->debug($err); - $this->debug("XML payload:\n" . $xml); - $this->setError($err); - } else { - $this->debug('in nusoap_parser ctor, message:'); - $this->appendDebug($this->varDump($this->message)); - $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name); - // get final value - $this->soapresponse = $this->message[$this->root_struct]['result']; - // get header value - if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){ - $this->soapheader = $this->message[$this->root_header]['result']; - } - // resolve hrefs/ids - if(sizeof($this->multirefs) > 0){ - foreach($this->multirefs as $id => $hrefs){ - $this->debug('resolving multirefs for id: '.$id); - $idVal = $this->buildVal($this->ids[$id]); - if (is_array($idVal) && isset($idVal['!id'])) { - unset($idVal['!id']); - } - foreach($hrefs as $refPos => $ref){ - $this->debug('resolving href at pos '.$refPos); - $this->multirefs[$id][$refPos] = $idVal; - } - } - } - } - xml_parser_free($this->parser); - } else { - $this->debug('xml was empty, didn\'t parse!'); - $this->setError('xml was empty, didn\'t parse!'); - } - } - - /** - * start-element handler - * - * @param resource $parser XML parser object - * @param string $name element name - * @param array $attrs associative array of attributes - * @access private - */ - function start_element($parser, $name, $attrs) { - // position in a total number of elements, starting from 0 - // update class level pos - $pos = $this->position++; - // and set mine - $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>''); - // depth = how many levels removed from root? - // set mine as current global depth and increment global depth value - $this->message[$pos]['depth'] = $this->depth++; - - // else add self as child to whoever the current parent is - if($pos != 0){ - $this->message[$this->parent]['children'] .= '|'.$pos; - } - // set my parent - $this->message[$pos]['parent'] = $this->parent; - // set self as current parent - $this->parent = $pos; - // set self as current value for this depth - $this->depth_array[$this->depth] = $pos; - // get element prefix - if(strpos($name,':')){ - // get ns prefix - $prefix = substr($name,0,strpos($name,':')); - // get unqualified name - $name = substr(strstr($name,':'),1); - } - // set status - if ($name == 'Envelope' && $this->status == '') { - $this->status = 'envelope'; - } elseif ($name == 'Header' && $this->status == 'envelope') { - $this->root_header = $pos; - $this->status = 'header'; - } elseif ($name == 'Body' && $this->status == 'envelope'){ - $this->status = 'body'; - $this->body_position = $pos; - // set method - } elseif($this->status == 'body' && $pos == ($this->body_position+1)) { - $this->status = 'method'; - $this->root_struct_name = $name; - $this->root_struct = $pos; - $this->message[$pos]['type'] = 'struct'; - $this->debug("found root struct $this->root_struct_name, pos $this->root_struct"); - } - // set my status - $this->message[$pos]['status'] = $this->status; - // set name - $this->message[$pos]['name'] = htmlspecialchars($name); - // set attrs - $this->message[$pos]['attrs'] = $attrs; - - // loop through atts, logging ns and type declarations - $attstr = ''; - foreach($attrs as $key => $value){ - $key_prefix = $this->getPrefix($key); - $key_localpart = $this->getLocalPart($key); - // if ns declarations, add to class level array of valid namespaces - if($key_prefix == 'xmlns'){ - if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){ - $this->XMLSchemaVersion = $value; - $this->namespaces['xsd'] = $this->XMLSchemaVersion; - $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance'; - } - $this->namespaces[$key_localpart] = $value; - // set method namespace - if($name == $this->root_struct_name){ - $this->methodNamespace = $value; - } - // if it's a type declaration, set type - } elseif($key_localpart == 'type'){ - if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') { - // do nothing: already processed arrayType - } else { - $value_prefix = $this->getPrefix($value); - $value_localpart = $this->getLocalPart($value); - $this->message[$pos]['type'] = $value_localpart; - $this->message[$pos]['typePrefix'] = $value_prefix; - if(isset($this->namespaces[$value_prefix])){ - $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix]; - } else if(isset($attrs['xmlns:'.$value_prefix])) { - $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix]; - } - // should do something here with the namespace of specified type? - } - } elseif($key_localpart == 'arrayType'){ - $this->message[$pos]['type'] = 'array'; - /* do arrayType ereg here - [1] arrayTypeValue ::= atype asize - [2] atype ::= QName rank* - [3] rank ::= '[' (',')* ']' - [4] asize ::= '[' length~ ']' - [5] length ::= nextDimension* Digit+ - [6] nextDimension ::= Digit+ ',' - */ - $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/'; - if(preg_match($expr,$value,$regs)){ - $this->message[$pos]['typePrefix'] = $regs[1]; - $this->message[$pos]['arrayTypePrefix'] = $regs[1]; - if (isset($this->namespaces[$regs[1]])) { - $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]]; - } else if (isset($attrs['xmlns:'.$regs[1]])) { - $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]]; - } - $this->message[$pos]['arrayType'] = $regs[2]; - $this->message[$pos]['arraySize'] = $regs[3]; - $this->message[$pos]['arrayCols'] = $regs[4]; - } - // specifies nil value (or not) - } elseif ($key_localpart == 'nil'){ - $this->message[$pos]['nil'] = ($value == 'true' || $value == '1'); - // some other attribute - } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') { - $this->message[$pos]['xattrs']['!' . $key] = $value; - } - - if ($key == 'xmlns') { - $this->default_namespace = $value; - } - // log id - if($key == 'id'){ - $this->ids[$value] = $pos; - } - // root - if($key_localpart == 'root' && $value == 1){ - $this->status = 'method'; - $this->root_struct_name = $name; - $this->root_struct = $pos; - $this->debug("found root struct $this->root_struct_name, pos $pos"); - } - // for doclit - $attstr .= " $key=\"$value\""; - } - // get namespace - must be done after namespace atts are processed - if(isset($prefix)){ - $this->message[$pos]['namespace'] = $this->namespaces[$prefix]; - $this->default_namespace = $this->namespaces[$prefix]; - } else { - $this->message[$pos]['namespace'] = $this->default_namespace; - } - if($this->status == 'header'){ - if ($this->root_header != $pos) { - $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>"; - } - } elseif($this->root_struct_name != ''){ - $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>"; - } - } - - /** - * end-element handler - * - * @param resource $parser XML parser object - * @param string $name element name - * @access private - */ - function end_element($parser, $name) { - // position of current element is equal to the last value left in depth_array for my depth - $pos = $this->depth_array[$this->depth--]; - - // get element prefix - if(strpos($name,':')){ - // get ns prefix - $prefix = substr($name,0,strpos($name,':')); - // get unqualified name - $name = substr(strstr($name,':'),1); - } - - // build to native type - if(isset($this->body_position) && $pos > $this->body_position){ - // deal w/ multirefs - if(isset($this->message[$pos]['attrs']['href'])){ - // get id - $id = substr($this->message[$pos]['attrs']['href'],1); - // add placeholder to href array - $this->multirefs[$id][$pos] = 'placeholder'; - // add set a reference to it as the result value - $this->message[$pos]['result'] =& $this->multirefs[$id][$pos]; - // build complexType values - } elseif($this->message[$pos]['children'] != ''){ - // if result has already been generated (struct/array) - if(!isset($this->message[$pos]['result'])){ - $this->message[$pos]['result'] = $this->buildVal($pos); - } - // build complexType values of attributes and possibly simpleContent - } elseif (isset($this->message[$pos]['xattrs'])) { - if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) { - $this->message[$pos]['xattrs']['!'] = null; - } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') { - if (isset($this->message[$pos]['type'])) { - $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - } else { - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - } else { - $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata']; - } - } - } - $this->message[$pos]['result'] = $this->message[$pos]['xattrs']; - // set value of simpleType (or nil complexType) - } else { - //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']); - if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) { - $this->message[$pos]['xattrs']['!'] = null; - } elseif (isset($this->message[$pos]['type'])) { - $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - } else { - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - } else { - $this->message[$pos]['result'] = $this->message[$pos]['cdata']; - } - } - - /* add value to parent's result, if parent is struct/array - $parent = $this->message[$pos]['parent']; - if($this->message[$parent]['type'] != 'map'){ - if(strtolower($this->message[$parent]['type']) == 'array'){ - $this->message[$parent]['result'][] = $this->message[$pos]['result']; - } else { - $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result']; - } - } - */ - } - } - - // for doclit - if($this->status == 'header'){ - if ($this->root_header != $pos) { - $this->responseHeaders .= ""; - } - } elseif($pos >= $this->root_struct){ - $this->document .= ""; - } - // switch status - if ($pos == $this->root_struct){ - $this->status = 'body'; - $this->root_struct_namespace = $this->message[$pos]['namespace']; - } elseif ($pos == $this->root_header) { - $this->status = 'envelope'; - } elseif ($name == 'Body' && $this->status == 'body') { - $this->status = 'envelope'; - } elseif ($name == 'Header' && $this->status == 'header') { // will never happen - $this->status = 'envelope'; - } elseif ($name == 'Envelope' && $this->status == 'envelope') { - $this->status = ''; - } - // set parent back to my parent - $this->parent = $this->message[$pos]['parent']; - } - - /** - * element content handler - * - * @param resource $parser XML parser object - * @param string $data element content - * @access private - */ - function character_data($parser, $data){ - $pos = $this->depth_array[$this->depth]; - if ($this->xml_encoding=='UTF-8'){ - // TODO: add an option to disable this for folks who want - // raw UTF-8 that, e.g., might not map to iso-8859-1 - // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1"); - if($this->decode_utf8){ - $data = utf8_decode($data); - } - } - $this->message[$pos]['cdata'] .= $data; - // for doclit - if($this->status == 'header'){ - $this->responseHeaders .= $data; - } else { - $this->document .= $data; - } - } - - /** - * get the parsed message (SOAP Body) - * - * @return mixed - * @access public - * @deprecated use get_soapbody instead - */ - function get_response(){ - return $this->soapresponse; - } - - /** - * get the parsed SOAP Body (NULL if there was none) - * - * @return mixed - * @access public - */ - function get_soapbody(){ - return $this->soapresponse; - } - - /** - * get the parsed SOAP Header (NULL if there was none) - * - * @return mixed - * @access public - */ - function get_soapheader(){ - return $this->soapheader; - } - - /** - * get the unparsed SOAP Header - * - * @return string XML or empty if no Header - * @access public - */ - function getHeaders(){ - return $this->responseHeaders; - } - - /** - * decodes simple types into PHP variables - * - * @param string $value value to decode - * @param string $type XML type to decode - * @param string $typens XML type namespace to decode - * @return mixed PHP value - * @access private - */ - function decodeSimple($value, $type, $typens) { - // TODO: use the namespace! - if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') { - return (string) $value; - } - if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') { - return (int) $value; - } - if ($type == 'float' || $type == 'double' || $type == 'decimal') { - return (double) $value; - } - if ($type == 'boolean') { - if (strtolower($value) == 'false' || strtolower($value) == 'f') { - return false; - } - return (boolean) $value; - } - if ($type == 'base64' || $type == 'base64Binary') { - $this->debug('Decode base64 value'); - return base64_decode($value); - } - // obscure numeric types - if ($type == 'nonPositiveInteger' || $type == 'negativeInteger' - || $type == 'nonNegativeInteger' || $type == 'positiveInteger' - || $type == 'unsignedInt' - || $type == 'unsignedShort' || $type == 'unsignedByte') { - return (int) $value; - } - // bogus: parser treats array with no elements as a simple type - if ($type == 'array') { - return array(); - } - // everything else - return (string) $value; - } - - /** - * builds response structures for compound values (arrays/structs) - * and scalars - * - * @param integer $pos position in node tree - * @return mixed PHP value - * @access private - */ - function buildVal($pos){ - if(!isset($this->message[$pos]['type'])){ - $this->message[$pos]['type'] = ''; - } - $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']); - // if there are children... - if($this->message[$pos]['children'] != ''){ - $this->debug('in buildVal, there are children'); - $children = explode('|',$this->message[$pos]['children']); - array_shift($children); // knock off empty - // md array - if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){ - $r=0; // rowcount - $c=0; // colcount - foreach($children as $child_pos){ - $this->debug("in buildVal, got an MD array element: $r, $c"); - $params[$r][] = $this->message[$child_pos]['result']; - $c++; - if($c == $this->message[$pos]['arrayCols']){ - $c = 0; - $r++; - } - } - // array - } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){ - $this->debug('in buildVal, adding array '.$this->message[$pos]['name']); - foreach($children as $child_pos){ - $params[] = &$this->message[$child_pos]['result']; - } - // apache Map type: java hashtable - } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){ - $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']); - foreach($children as $child_pos){ - $kv = explode("|",$this->message[$child_pos]['children']); - $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result']; - } - // generic compound type - //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') { - } else { - // Apache Vector type: treat as an array - $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']); - if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') { - $notstruct = 1; - } else { - $notstruct = 0; - } - // - foreach($children as $child_pos){ - if($notstruct){ - $params[] = &$this->message[$child_pos]['result']; - } else { - if (isset($params[$this->message[$child_pos]['name']])) { - // de-serialize repeated element name into an array - if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) { - $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]); - } - $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result']; - } else { - $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result']; - } - } - } - } - if (isset($this->message[$pos]['xattrs'])) { - $this->debug('in buildVal, handling attributes'); - foreach ($this->message[$pos]['xattrs'] as $n => $v) { - $params[$n] = $v; - } - } - // handle simpleContent - if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') { - $this->debug('in buildVal, handling simpleContent'); - if (isset($this->message[$pos]['type'])) { - $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - } else { - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - } else { - $params['!'] = $this->message[$pos]['cdata']; - } - } - } - $ret = is_array($params) ? $params : array(); - $this->debug('in buildVal, return:'); - $this->appendDebug($this->varDump($ret)); - return $ret; - } else { - $this->debug('in buildVal, no children, building scalar'); - $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : ''; - if (isset($this->message[$pos]['type'])) { - $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - $this->debug("in buildVal, return: $ret"); - return $ret; - } - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - $this->debug("in buildVal, return: $ret"); - return $ret; - } - $ret = $this->message[$pos]['cdata']; - $this->debug("in buildVal, return: $ret"); - return $ret; - } - } -} - -/** - * Backward compatibility - */ -class soap_parser extends nusoap_parser { -} - - -?> \ No newline at end of file diff --git a/lib/nusoap/class.soap_server.php b/lib/nusoap/class.soap_server.php deleted file mode 100644 index 4f1321d3f..000000000 --- a/lib/nusoap/class.soap_server.php +++ /dev/null @@ -1,1127 +0,0 @@ - -* @author Scott Nichol -* @version $Id: class.soap_server.php,v 1.63 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_server extends nusoap_base { - /** - * HTTP headers of request - * @var array - * @access private - */ - var $headers = array(); - /** - * HTTP request - * @var string - * @access private - */ - var $request = ''; - /** - * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text) - * @var string - * @access public - */ - var $requestHeaders = ''; - /** - * SOAP Headers from request (parsed) - * @var mixed - * @access public - */ - var $requestHeader = NULL; - /** - * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text) - * @var string - * @access public - */ - var $document = ''; - /** - * SOAP payload for request (text) - * @var string - * @access public - */ - var $requestSOAP = ''; - /** - * requested method namespace URI - * @var string - * @access private - */ - var $methodURI = ''; - /** - * name of method requested - * @var string - * @access private - */ - var $methodname = ''; - /** - * method parameters from request - * @var array - * @access private - */ - var $methodparams = array(); - /** - * SOAP Action from request - * @var string - * @access private - */ - var $SOAPAction = ''; - /** - * character set encoding of incoming (request) messages - * @var string - * @access public - */ - var $xml_encoding = ''; - /** - * toggles whether the parser decodes element content w/ utf8_decode() - * @var boolean - * @access public - */ - var $decode_utf8 = true; - - /** - * HTTP headers of response - * @var array - * @access public - */ - var $outgoing_headers = array(); - /** - * HTTP response - * @var string - * @access private - */ - var $response = ''; - /** - * SOAP headers for response (text or array of soapval or associative array) - * @var mixed - * @access public - */ - var $responseHeaders = ''; - /** - * SOAP payload for response (text) - * @var string - * @access private - */ - var $responseSOAP = ''; - /** - * method return value to place in response - * @var mixed - * @access private - */ - var $methodreturn = false; - /** - * whether $methodreturn is a string of literal XML - * @var boolean - * @access public - */ - var $methodreturnisliteralxml = false; - /** - * SOAP fault for response (or false) - * @var mixed - * @access private - */ - var $fault = false; - /** - * text indication of result (for debugging) - * @var string - * @access private - */ - var $result = 'successful'; - - /** - * assoc array of operations => opData; operations are added by the register() - * method or by parsing an external WSDL definition - * @var array - * @access private - */ - var $operations = array(); - /** - * wsdl instance (if one) - * @var mixed - * @access private - */ - var $wsdl = false; - /** - * URL for WSDL (if one) - * @var mixed - * @access private - */ - var $externalWSDLURL = false; - /** - * whether to append debug to response as XML comment - * @var boolean - * @access public - */ - var $debug_flag = false; - - - /** - * constructor - * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to. - * - * @param mixed $wsdl file path or URL (string), or wsdl instance (object) - * @access public - */ - function nusoap_server($wsdl=false){ - parent::nusoap_base(); - // turn on debugging? - global $debug; - global $HTTP_SERVER_VARS; - - if (isset($_SERVER)) { - $this->debug("_SERVER is defined:"); - $this->appendDebug($this->varDump($_SERVER)); - } elseif (isset($HTTP_SERVER_VARS)) { - $this->debug("HTTP_SERVER_VARS is defined:"); - $this->appendDebug($this->varDump($HTTP_SERVER_VARS)); - } else { - $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined."); - } - - if (isset($debug)) { - $this->debug("In nusoap_server, set debug_flag=$debug based on global flag"); - $this->debug_flag = $debug; - } elseif (isset($_SERVER['QUERY_STRING'])) { - $qs = explode('&', $_SERVER['QUERY_STRING']); - foreach ($qs as $v) { - if (substr($v, 0, 6) == 'debug=') { - $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1"); - $this->debug_flag = substr($v, 6); - } - } - } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) { - $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']); - foreach ($qs as $v) { - if (substr($v, 0, 6) == 'debug=') { - $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2"); - $this->debug_flag = substr($v, 6); - } - } - } - - // wsdl - if($wsdl){ - $this->debug("In nusoap_server, WSDL is specified"); - if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) { - $this->wsdl = $wsdl; - $this->externalWSDLURL = $this->wsdl->wsdl; - $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL); - } else { - $this->debug('Create wsdl from ' . $wsdl); - $this->wsdl = new wsdl($wsdl); - $this->externalWSDLURL = $wsdl; - } - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - if($err = $this->wsdl->getError()){ - die('WSDL ERROR: '.$err); - } - } - } - - /** - * processes request and returns response - * - * @param string $data usually is the value of $HTTP_RAW_POST_DATA - * @access public - */ - function service($data){ - global $HTTP_SERVER_VARS; - - if (isset($_SERVER['REQUEST_METHOD'])) { - $rm = $_SERVER['REQUEST_METHOD']; - } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) { - $rm = $HTTP_SERVER_VARS['REQUEST_METHOD']; - } else { - $rm = ''; - } - - if (isset($_SERVER['QUERY_STRING'])) { - $qs = $_SERVER['QUERY_STRING']; - } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) { - $qs = $HTTP_SERVER_VARS['QUERY_STRING']; - } else { - $qs = ''; - } - $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data)); - - if ($rm == 'POST') { - $this->debug("In service, invoke the request"); - $this->parse_request($data); - if (! $this->fault) { - $this->invoke_method(); - } - if (! $this->fault) { - $this->serialize_return(); - } - $this->send_response(); - } elseif (preg_match('/wsdl/', $qs) ){ - $this->debug("In service, this is a request for WSDL"); - if ($this->externalWSDLURL){ - if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL - $this->debug("In service, re-direct for WSDL"); - header('Location: '.$this->externalWSDLURL); - } else { // assume file - $this->debug("In service, use file passthru for WSDL"); - header("Content-Type: text/xml\r\n"); - $pos = strpos($this->externalWSDLURL, "file://"); - if ($pos === false) { - $filename = $this->externalWSDLURL; - } else { - $filename = substr($this->externalWSDLURL, $pos + 7); - } - $fp = fopen($this->externalWSDLURL, 'r'); - fpassthru($fp); - } - } elseif ($this->wsdl) { - $this->debug("In service, serialize WSDL"); - header("Content-Type: text/xml; charset=ISO-8859-1\r\n"); - print $this->wsdl->serialize($this->debug_flag); - if ($this->debug_flag) { - $this->debug('wsdl:'); - $this->appendDebug($this->varDump($this->wsdl)); - print $this->getDebugAsXMLComment(); - } - } else { - $this->debug("In service, there is no WSDL"); - header("Content-Type: text/html; charset=ISO-8859-1\r\n"); - print "This service does not provide WSDL"; - } - } elseif ($this->wsdl) { - $this->debug("In service, return Web description"); - print $this->wsdl->webDescription(); - } else { - $this->debug("In service, no Web description"); - header("Content-Type: text/html; charset=ISO-8859-1\r\n"); - print "This service does not provide a Web description"; - } - } - - /** - * parses HTTP request headers. - * - * The following fields are set by this function (when successful) - * - * headers - * request - * xml_encoding - * SOAPAction - * - * @access private - */ - function parse_http_headers() { - global $HTTP_SERVER_VARS; - - $this->request = ''; - $this->SOAPAction = ''; - if(function_exists('getallheaders')){ - $this->debug("In parse_http_headers, use getallheaders"); - $headers = getallheaders(); - foreach($headers as $k=>$v){ - $k = strtolower($k); - $this->headers[$k] = $v; - $this->request .= "$k: $v\r\n"; - $this->debug("$k: $v"); - } - // get SOAPAction header - if(isset($this->headers['soapaction'])){ - $this->SOAPAction = str_replace('"','',$this->headers['soapaction']); - } - // get the character encoding of the incoming request - if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){ - $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1)); - if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){ - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - } elseif(isset($_SERVER) && is_array($_SERVER)){ - $this->debug("In parse_http_headers, use _SERVER"); - foreach ($_SERVER as $k => $v) { - if (substr($k, 0, 5) == 'HTTP_') { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); - } else { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); - } - if ($k == 'soapaction') { - // get SOAPAction header - $k = 'SOAPAction'; - $v = str_replace('"', '', $v); - $v = str_replace('\\', '', $v); - $this->SOAPAction = $v; - } else if ($k == 'content-type') { - // get the character encoding of the incoming request - if (strpos($v, '=')) { - $enc = substr(strstr($v, '='), 1); - $enc = str_replace('"', '', $enc); - $enc = str_replace('\\', '', $enc); - if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) { - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - } - $this->headers[$k] = $v; - $this->request .= "$k: $v\r\n"; - $this->debug("$k: $v"); - } - } elseif (is_array($HTTP_SERVER_VARS)) { - $this->debug("In parse_http_headers, use HTTP_SERVER_VARS"); - foreach ($HTTP_SERVER_VARS as $k => $v) { - if (substr($k, 0, 5) == 'HTTP_') { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5)); - } else { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k); - } - if ($k == 'soapaction') { - // get SOAPAction header - $k = 'SOAPAction'; - $v = str_replace('"', '', $v); - $v = str_replace('\\', '', $v); - $this->SOAPAction = $v; - } else if ($k == 'content-type') { - // get the character encoding of the incoming request - if (strpos($v, '=')) { - $enc = substr(strstr($v, '='), 1); - $enc = str_replace('"', '', $enc); - $enc = str_replace('\\', '', $enc); - if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) { - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - } - $this->headers[$k] = $v; - $this->request .= "$k: $v\r\n"; - $this->debug("$k: $v"); - } - } else { - $this->debug("In parse_http_headers, HTTP headers not accessible"); - $this->setError("HTTP headers not accessible"); - } - } - - /** - * parses a request - * - * The following fields are set by this function (when successful) - * - * headers - * request - * xml_encoding - * SOAPAction - * request - * requestSOAP - * methodURI - * methodname - * methodparams - * requestHeaders - * document - * - * This sets the fault field on error - * - * @param string $data XML string - * @access private - */ - function parse_request($data='') { - $this->debug('entering parse_request()'); - $this->parse_http_headers(); - $this->debug('got character encoding: '.$this->xml_encoding); - // uncompress if necessary - if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') { - $this->debug('got content encoding: ' . $this->headers['content-encoding']); - if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') { - // if decoding works, use it. else assume data wasn't gzencoded - if (function_exists('gzuncompress')) { - if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) { - $data = $degzdata; - } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) { - $data = $degzdata; - } else { - $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data'); - return; - } - } else { - $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data'); - return; - } - } - } - $this->request .= "\r\n".$data; - $data = $this->parseRequest($this->headers, $data); - $this->requestSOAP = $data; - $this->debug('leaving parse_request'); - } - - /** - * invokes a PHP function for the requested SOAP method - * - * The following fields are set by this function (when successful) - * - * methodreturn - * - * Note that the PHP function that is called may also set the following - * fields to affect the response sent to the client - * - * responseHeaders - * outgoing_headers - * - * This sets the fault field on error - * - * @access private - */ - function invoke_method() { - $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction); - - // - // if you are debugging in this area of the code, your service uses a class to implement methods, - // you use SOAP RPC, and the client is .NET, please be aware of the following... - // when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the - // method name. that is fine for naming the .NET methods. it is not fine for properly constructing - // the XML request and reading the XML response. you need to add the RequestElementName and - // ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe - // generates for the method. these parameters are used to specify the correct XML element names - // for .NET to use, i.e. the names with the '.' in them. - // - $orig_methodname = $this->methodname; - if ($this->wsdl) { - if ($this->opData = $this->wsdl->getOperationData($this->methodname)) { - $this->debug('in invoke_method, found WSDL operation=' . $this->methodname); - $this->appendDebug('opData=' . $this->varDump($this->opData)); - } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) { - // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element - $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']); - $this->appendDebug('opData=' . $this->varDump($this->opData)); - $this->methodname = $this->opData['name']; - } else { - $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname); - $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service"); - return; - } - } else { - $this->debug('in invoke_method, no WSDL to validate method'); - } - - // if a . is present in $this->methodname, we see if there is a class in scope, - // which could be referred to. We will also distinguish between two deliminators, - // to allow methods to be called a the class or an instance - if (strpos($this->methodname, '..') > 0) { - $delim = '..'; - } else if (strpos($this->methodname, '.') > 0) { - $delim = '.'; - } else { - $delim = ''; - } - $this->debug("in invoke_method, delim=$delim"); - - $class = ''; - $method = ''; - if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) { - $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim)); - if (class_exists($try_class)) { - // get the class and method name - $class = $try_class; - $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim)); - $this->debug("in invoke_method, class=$class method=$method delim=$delim"); - } else { - $this->debug("in invoke_method, class=$try_class not found"); - } - } else { - $try_class = ''; - $this->debug("in invoke_method, no class to try"); - } - - // does method exist? - if ($class == '') { - if (!function_exists($this->methodname)) { - $this->debug("in invoke_method, function '$this->methodname' not found!"); - $this->result = 'fault: method not found'; - $this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')"); - return; - } - } else { - $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method; - if (!in_array($method_to_compare, get_class_methods($class))) { - $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!"); - $this->result = 'fault: method not found'; - $this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')"); - return; - } - } - - // evaluate message, getting back parameters - // verify that request parameters match the method's signature - if(! $this->verify_method($this->methodname,$this->methodparams)){ - // debug - $this->debug('ERROR: request not verified against method signature'); - $this->result = 'fault: request failed validation against method signature'; - // return fault - $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service."); - return; - } - - // if there are parameters to pass - $this->debug('in invoke_method, params:'); - $this->appendDebug($this->varDump($this->methodparams)); - $this->debug("in invoke_method, calling '$this->methodname'"); - if (!function_exists('call_user_func_array')) { - if ($class == '') { - $this->debug('in invoke_method, calling function using eval()'); - $funcCall = "\$this->methodreturn = $this->methodname("; - } else { - if ($delim == '..') { - $this->debug('in invoke_method, calling class method using eval()'); - $funcCall = "\$this->methodreturn = ".$class."::".$method."("; - } else { - $this->debug('in invoke_method, calling instance method using eval()'); - // generate unique instance name - $instname = "\$inst_".time(); - $funcCall = $instname." = new ".$class."(); "; - $funcCall .= "\$this->methodreturn = ".$instname."->".$method."("; - } - } - if ($this->methodparams) { - foreach ($this->methodparams as $param) { - if (is_array($param) || is_object($param)) { - $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available'); - return; - } - $funcCall .= "\"$param\","; - } - $funcCall = substr($funcCall, 0, -1); - } - $funcCall .= ');'; - $this->debug('in invoke_method, function call: '.$funcCall); - @eval($funcCall); - } else { - if ($class == '') { - $this->debug('in invoke_method, calling function using call_user_func_array()'); - $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array() - } elseif ($delim == '..') { - $this->debug('in invoke_method, calling class method using call_user_func_array()'); - $call_arg = array ($class, $method); - } else { - $this->debug('in invoke_method, calling instance method using call_user_func_array()'); - $instance = new $class (); - $call_arg = array(&$instance, $method); - } - if (is_array($this->methodparams)) { - $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams)); - } else { - $this->methodreturn = call_user_func_array($call_arg, array()); - } - } - $this->debug('in invoke_method, methodreturn:'); - $this->appendDebug($this->varDump($this->methodreturn)); - $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn)); - } - - /** - * serializes the return value from a PHP function into a full SOAP Envelope - * - * The following fields are set by this function (when successful) - * - * responseSOAP - * - * This sets the fault field on error - * - * @access private - */ - function serialize_return() { - $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI); - // if fault - if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) { - $this->debug('got a fault object from method'); - $this->fault = $this->methodreturn; - return; - } elseif ($this->methodreturnisliteralxml) { - $return_val = $this->methodreturn; - // returned value(s) - } else { - $this->debug('got a(n) '.gettype($this->methodreturn).' from method'); - $this->debug('serializing return value'); - if($this->wsdl){ - if (sizeof($this->opData['output']['parts']) > 1) { - $this->debug('more than one output part, so use the method return unchanged'); - $opParams = $this->methodreturn; - } elseif (sizeof($this->opData['output']['parts']) == 1) { - $this->debug('exactly one output part, so wrap the method return in a simple array'); - // TODO: verify that it is not already wrapped! - //foreach ($this->opData['output']['parts'] as $name => $type) { - // $this->debug('wrap in element named ' . $name); - //} - $opParams = array($this->methodreturn); - } - $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams); - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - if($errstr = $this->wsdl->getError()){ - $this->debug('got wsdl error: '.$errstr); - $this->fault('SOAP-ENV:Server', 'unable to serialize result'); - return; - } - } else { - if (isset($this->methodreturn)) { - $return_val = $this->serialize_val($this->methodreturn, 'return'); - } else { - $return_val = ''; - $this->debug('in absence of WSDL, assume void return for backward compatibility'); - } - } - } - $this->debug('return value:'); - $this->appendDebug($this->varDump($return_val)); - - $this->debug('serializing response'); - if ($this->wsdl) { - $this->debug('have WSDL for serialization: style is ' . $this->opData['style']); - if ($this->opData['style'] == 'rpc') { - $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']); - if ($this->opData['output']['use'] == 'literal') { - // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace - if ($this->methodURI) { - $payload = 'methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'methodname."Response>"; - } else { - $payload = '<'.$this->methodname.'Response>'.$return_val.'methodname.'Response>'; - } - } else { - if ($this->methodURI) { - $payload = 'methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'methodname."Response>"; - } else { - $payload = '<'.$this->methodname.'Response>'.$return_val.'methodname.'Response>'; - } - } - } else { - $this->debug('style is not rpc for serialization: assume document'); - $payload = $return_val; - } - } else { - $this->debug('do not have WSDL for serialization: assume rpc/encoded'); - $payload = 'methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'methodname."Response>"; - } - $this->result = 'successful'; - if($this->wsdl){ - //if($this->debug_flag){ - $this->appendDebug($this->wsdl->getDebug()); - // } - if (isset($this->opData['output']['encodingStyle'])) { - $encodingStyle = $this->opData['output']['encodingStyle']; - } else { - $encodingStyle = ''; - } - // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces. - $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle); - } else { - $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders); - } - $this->debug("Leaving serialize_return"); - } - - /** - * sends an HTTP response - * - * The following fields are set by this function (when successful) - * - * outgoing_headers - * response - * - * @access private - */ - function send_response() { - $this->debug('Enter send_response'); - if ($this->fault) { - $payload = $this->fault->serialize(); - $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error"; - $this->outgoing_headers[] = "Status: 500 Internal Server Error"; - } else { - $payload = $this->responseSOAP; - // Some combinations of PHP+Web server allow the Status - // to come through as a header. Since OK is the default - // just do nothing. - // $this->outgoing_headers[] = "HTTP/1.0 200 OK"; - // $this->outgoing_headers[] = "Status: 200 OK"; - } - // add debug data if in debug mode - if(isset($this->debug_flag) && $this->debug_flag){ - $payload .= $this->getDebugAsXMLComment(); - } - $this->outgoing_headers[] = "Server: $this->title Server v$this->version"; - preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev); - $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")"; - // Let the Web server decide about this - //$this->outgoing_headers[] = "Connection: Close\r\n"; - $payload = $this->getHTTPBody($payload); - $type = $this->getHTTPContentType(); - $charset = $this->getHTTPContentTypeCharset(); - $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : ''); - //begin code to compress payload - by John - // NOTE: there is no way to know whether the Web server will also compress - // this data. - if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) { - if (strstr($this->headers['accept-encoding'], 'gzip')) { - if (function_exists('gzencode')) { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ""; - } - $this->outgoing_headers[] = "Content-Encoding: gzip"; - $payload = gzencode($payload); - } else { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ""; - } - } - } elseif (strstr($this->headers['accept-encoding'], 'deflate')) { - // Note: MSIE requires gzdeflate output (no Zlib header and checksum), - // instead of gzcompress output, - // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5) - if (function_exists('gzdeflate')) { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ""; - } - $this->outgoing_headers[] = "Content-Encoding: deflate"; - $payload = gzdeflate($payload); - } else { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ""; - } - } - } - } - //end code - $this->outgoing_headers[] = "Content-Length: ".strlen($payload); - reset($this->outgoing_headers); - foreach($this->outgoing_headers as $hdr){ - header($hdr, false); - } - print $payload; - $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload; - } - - /** - * takes the value that was created by parsing the request - * and compares to the method's signature, if available. - * - * @param string $operation The operation to be invoked - * @param array $request The array of parameter values - * @return boolean Whether the operation was found - * @access private - */ - function verify_method($operation,$request){ - if(isset($this->wsdl) && is_object($this->wsdl)){ - if($this->wsdl->getOperationData($operation)){ - return true; - } - } elseif(isset($this->operations[$operation])){ - return true; - } - return false; - } - - /** - * processes SOAP message received from client - * - * @param array $headers The HTTP headers - * @param string $data unprocessed request data from client - * @return mixed value of the message, decoded into a PHP type - * @access private - */ - function parseRequest($headers, $data) { - $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:'); - $this->appendDebug($this->varDump($headers)); - if (!isset($headers['content-type'])) { - $this->setError('Request not of type text/xml (no content-type header)'); - return false; - } - if (!strstr($headers['content-type'], 'text/xml')) { - $this->setError('Request not of type text/xml'); - return false; - } - if (strpos($headers['content-type'], '=')) { - $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1)); - $this->debug('Got response encoding: ' . $enc); - if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){ - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser'); - // parse response, get soap parser obj - $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8); - // parser debug - $this->debug("parser debug: \n".$parser->getDebug()); - // if fault occurred during message parsing - if($err = $parser->getError()){ - $this->result = 'fault: error in msg parsing: '.$err; - $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err); - // else successfully parsed request into soapval object - } else { - // get/set methodname - $this->methodURI = $parser->root_struct_namespace; - $this->methodname = $parser->root_struct_name; - $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI); - $this->debug('calling parser->get_soapbody()'); - $this->methodparams = $parser->get_soapbody(); - // get SOAP headers - $this->requestHeaders = $parser->getHeaders(); - // get SOAP Header - $this->requestHeader = $parser->get_soapheader(); - // add document for doclit support - $this->document = $parser->document; - } - } - - /** - * gets the HTTP body for the current response. - * - * @param string $soapmsg The SOAP payload - * @return string The HTTP body, which includes the SOAP payload - * @access private - */ - function getHTTPBody($soapmsg) { - return $soapmsg; - } - - /** - * gets the HTTP content type for the current response. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type for the current response. - * @access private - */ - function getHTTPContentType() { - return 'text/xml'; - } - - /** - * gets the HTTP content type charset for the current response. - * returns false for non-text content types. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type charset for the current response. - * @access private - */ - function getHTTPContentTypeCharset() { - return $this->soap_defencoding; - } - - /** - * add a method to the dispatch map (this has been replaced by the register method) - * - * @param string $methodname - * @param string $in array of input values - * @param string $out array of output values - * @access public - * @deprecated - */ - function add_to_map($methodname,$in,$out){ - $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out); - } - - /** - * register a service function with the server - * - * @param string $name the name of the PHP function, class.method or class..method - * @param array $in assoc array of input values: key = param name, value = param type - * @param array $out assoc array of output values: key = param name, value = param type - * @param mixed $namespace the element namespace for the method or false - * @param mixed $soapaction the soapaction for the method or false - * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically - * @param mixed $use optional (encoded|literal) or false - * @param string $documentation optional Description to include in WSDL - * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) - * @access public - */ - function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){ - global $HTTP_SERVER_VARS; - - if($this->externalWSDLURL){ - die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.'); - } - if (! $name) { - die('You must specify a name when you register an operation'); - } - if (!is_array($in)) { - die('You must provide an array for operation inputs'); - } - if (!is_array($out)) { - die('You must provide an array for operation outputs'); - } - if(false == $namespace) { - } - if(false == $soapaction) { - if (isset($_SERVER)) { - $SERVER_NAME = $_SERVER['SERVER_NAME']; - $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']; - $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'); - } elseif (isset($HTTP_SERVER_VARS)) { - $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME']; - $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME']; - $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'; - } else { - $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); - } - if ($HTTPS == '1' || $HTTPS == 'on') { - $SCHEME = 'https'; - } else { - $SCHEME = 'http'; - } - $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name"; - } - if(false == $style) { - $style = "rpc"; - } - if(false == $use) { - $use = "encoded"; - } - if ($use == 'encoded' && $encodingStyle == '') { - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - } - - $this->operations[$name] = array( - 'name' => $name, - 'in' => $in, - 'out' => $out, - 'namespace' => $namespace, - 'soapaction' => $soapaction, - 'style' => $style); - if($this->wsdl){ - $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle); - } - return true; - } - - /** - * Specify a fault to be returned to the client. - * This also acts as a flag to the server that a fault has occured. - * - * @param string $faultcode - * @param string $faultstring - * @param string $faultactor - * @param string $faultdetail - * @access public - */ - function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){ - if ($faultdetail == '' && $this->debug_flag) { - $faultdetail = $this->getDebug(); - } - $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail); - $this->fault->soap_defencoding = $this->soap_defencoding; - } - - /** - * Sets up wsdl object. - * Acts as a flag to enable internal WSDL generation - * - * @param string $serviceName, name of the service - * @param mixed $namespace optional 'tns' service namespace or false - * @param mixed $endpoint optional URL of service endpoint or false - * @param string $style optional (rpc|document) WSDL style (also specified by operation) - * @param string $transport optional SOAP transport - * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false - */ - function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false) - { - global $HTTP_SERVER_VARS; - - if (isset($_SERVER)) { - $SERVER_NAME = $_SERVER['SERVER_NAME']; - $SERVER_PORT = $_SERVER['SERVER_PORT']; - $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']; - $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'); - } elseif (isset($HTTP_SERVER_VARS)) { - $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME']; - $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT']; - $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME']; - $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'; - } else { - $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); - } - // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI) - $colon = strpos($SERVER_NAME,":"); - if ($colon) { - $SERVER_NAME = substr($SERVER_NAME, 0, $colon); - } - if ($SERVER_PORT == 80) { - $SERVER_PORT = ''; - } else { - $SERVER_PORT = ':' . $SERVER_PORT; - } - if(false == $namespace) { - $namespace = "http://$SERVER_NAME/soap/$serviceName"; - } - - if(false == $endpoint) { - if ($HTTPS == '1' || $HTTPS == 'on') { - $SCHEME = 'https'; - } else { - $SCHEME = 'http'; - } - $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME"; - } - - if(false == $schemaTargetNamespace) { - $schemaTargetNamespace = $namespace; - } - - $this->wsdl = new wsdl; - $this->wsdl->serviceName = $serviceName; - $this->wsdl->endpoint = $endpoint; - $this->wsdl->namespaces['tns'] = $namespace; - $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/'; - $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/'; - if ($schemaTargetNamespace != $namespace) { - $this->wsdl->namespaces['types'] = $schemaTargetNamespace; - } - $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces); - if ($style == 'document') { - $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified'; - } - $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace; - $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true); - $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true); - $this->wsdl->bindings[$serviceName.'Binding'] = array( - 'name'=>$serviceName.'Binding', - 'style'=>$style, - 'transport'=>$transport, - 'portType'=>$serviceName.'PortType'); - $this->wsdl->ports[$serviceName.'Port'] = array( - 'binding'=>$serviceName.'Binding', - 'location'=>$endpoint, - 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/'); - } -} - -/** - * Backward compatibility - */ -class soap_server extends nusoap_server { -} - - -?> \ No newline at end of file diff --git a/lib/nusoap/class.soap_transport_http.php b/lib/nusoap/class.soap_transport_http.php deleted file mode 100644 index 469820934..000000000 --- a/lib/nusoap/class.soap_transport_http.php +++ /dev/null @@ -1,1307 +0,0 @@ - -* @author Scott Nichol -* @version $Id: class.soap_transport_http.php,v 1.68 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class soap_transport_http extends nusoap_base { - - var $url = ''; - var $uri = ''; - var $digest_uri = ''; - var $scheme = ''; - var $host = ''; - var $port = ''; - var $path = ''; - var $request_method = 'POST'; - var $protocol_version = '1.0'; - var $encoding = ''; - var $outgoing_headers = array(); - var $incoming_headers = array(); - var $incoming_cookies = array(); - var $outgoing_payload = ''; - var $incoming_payload = ''; - var $response_status_line; // HTTP response status line - var $useSOAPAction = true; - var $persistentConnection = false; - var $ch = false; // cURL handle - var $ch_options = array(); // cURL custom options - var $use_curl = false; // force cURL use - var $proxy = null; // proxy information (associative array) - var $username = ''; - var $password = ''; - var $authtype = ''; - var $digestRequest = array(); - var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional) - // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem' - // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem' - // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem' - // passphrase: SSL key password/passphrase - // certpassword: SSL certificate password - // verifypeer: default is 1 - // verifyhost: default is 1 - - /** - * constructor - * - * @param string $url The URL to which to connect - * @param array $curl_options User-specified cURL options - * @param boolean $use_curl Whether to try to force cURL use - * @access public - */ - function soap_transport_http($url, $curl_options = NULL, $use_curl = false){ - parent::nusoap_base(); - $this->debug("ctor url=$url use_curl=$use_curl curl_options:"); - $this->appendDebug($this->varDump($curl_options)); - $this->setURL($url); - if (is_array($curl_options)) { - $this->ch_options = $curl_options; - } - $this->use_curl = $use_curl; - preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev); - $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')'); - } - - /** - * sets a cURL option - * - * @param mixed $option The cURL option (always integer?) - * @param mixed $value The cURL option value - * @access private - */ - function setCurlOption($option, $value) { - $this->debug("setCurlOption option=$option, value="); - $this->appendDebug($this->varDump($value)); - curl_setopt($this->ch, $option, $value); - } - - /** - * sets an HTTP header - * - * @param string $name The name of the header - * @param string $value The value of the header - * @access private - */ - function setHeader($name, $value) { - $this->outgoing_headers[$name] = $value; - $this->debug("set header $name: $value"); - } - - /** - * unsets an HTTP header - * - * @param string $name The name of the header - * @access private - */ - function unsetHeader($name) { - if (isset($this->outgoing_headers[$name])) { - $this->debug("unset header $name"); - unset($this->outgoing_headers[$name]); - } - } - - /** - * sets the URL to which to connect - * - * @param string $url The URL to which to connect - * @access private - */ - function setURL($url) { - $this->url = $url; - - $u = parse_url($url); - foreach($u as $k => $v){ - $this->debug("parsed URL $k = $v"); - $this->$k = $v; - } - - // add any GET params to path - if(isset($u['query']) && $u['query'] != ''){ - $this->path .= '?' . $u['query']; - } - - // set default port - if(!isset($u['port'])){ - if($u['scheme'] == 'https'){ - $this->port = 443; - } else { - $this->port = 80; - } - } - - $this->uri = $this->path; - $this->digest_uri = $this->uri; - - // build headers - if (!isset($u['port'])) { - $this->setHeader('Host', $this->host); - } else { - $this->setHeader('Host', $this->host.':'.$this->port); - } - - if (isset($u['user']) && $u['user'] != '') { - $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : ''); - } - } - - /** - * gets the I/O method to use - * - * @return string I/O method to use (socket|curl|unknown) - * @access private - */ - function io_method() { - if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm')) - return 'curl'; - if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm')) - return 'socket'; - return 'unknown'; - } - - /** - * establish an HTTP connection - * - * @param integer $timeout set connection timeout in seconds - * @param integer $response_timeout set response timeout in seconds - * @return boolean true if connected, false if not - * @access private - */ - function connect($connection_timeout=0,$response_timeout=30){ - // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like - // "regular" socket. - // TODO: disabled for now because OpenSSL must be *compiled* in (not just - // loaded), and until PHP5 stream_get_wrappers is not available. -// if ($this->scheme == 'https') { -// if (version_compare(phpversion(), '4.3.0') >= 0) { -// if (extension_loaded('openssl')) { -// $this->scheme = 'ssl'; -// $this->debug('Using SSL over OpenSSL'); -// } -// } -// } - $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port"); - if ($this->io_method() == 'socket') { - if (!is_array($this->proxy)) { - $host = $this->host; - $port = $this->port; - } else { - $host = $this->proxy['host']; - $port = $this->proxy['port']; - } - - // use persistent connection - if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){ - if (!feof($this->fp)) { - $this->debug('Re-use persistent connection'); - return true; - } - fclose($this->fp); - $this->debug('Closed persistent connection at EOF'); - } - - // munge host if using OpenSSL - if ($this->scheme == 'ssl') { - $host = 'ssl://' . $host; - } - $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout); - - // open socket - if($connection_timeout > 0){ - $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout); - } else { - $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str); - } - - // test pointer - if(!$this->fp) { - $msg = 'Couldn\'t open socket connection to server ' . $this->url; - if ($this->errno) { - $msg .= ', Error ('.$this->errno.'): '.$this->error_str; - } else { - $msg .= ' prior to connect(). This is often a problem looking up the host name.'; - } - $this->debug($msg); - $this->setError($msg); - return false; - } - - // set response timeout - $this->debug('set response timeout to ' . $response_timeout); - socket_set_timeout( $this->fp, $response_timeout); - - $this->debug('socket connected'); - return true; - } else if ($this->io_method() == 'curl') { - if (!extension_loaded('curl')) { -// $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS'); - $this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to include cURL or change php.ini to load the PHP cURL extension.'); - return false; - } - // Avoid warnings when PHP does not have these options - if (defined('CURLOPT_CONNECTIONTIMEOUT')) - $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT; - else - $CURLOPT_CONNECTIONTIMEOUT = 78; - if (defined('CURLOPT_HTTPAUTH')) - $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH; - else - $CURLOPT_HTTPAUTH = 107; - if (defined('CURLOPT_PROXYAUTH')) - $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH; - else - $CURLOPT_PROXYAUTH = 111; - if (defined('CURLAUTH_BASIC')) - $CURLAUTH_BASIC = CURLAUTH_BASIC; - else - $CURLAUTH_BASIC = 1; - if (defined('CURLAUTH_DIGEST')) - $CURLAUTH_DIGEST = CURLAUTH_DIGEST; - else - $CURLAUTH_DIGEST = 2; - if (defined('CURLAUTH_NTLM')) - $CURLAUTH_NTLM = CURLAUTH_NTLM; - else - $CURLAUTH_NTLM = 8; - - $this->debug('connect using cURL'); - // init CURL - $this->ch = curl_init(); - // set url - $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host"; - // add path - $hostURL .= $this->path; - $this->setCurlOption(CURLOPT_URL, $hostURL); - // follow location headers (re-directs) - if (ini_get('safe_mode') || ini_get('open_basedir')) { - $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION'); - $this->debug('safe_mode = '); - $this->appendDebug($this->varDump(ini_get('safe_mode'))); - $this->debug('open_basedir = '); - $this->appendDebug($this->varDump(ini_get('open_basedir'))); - } else { - $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1); - } - // ask for headers in the response output - $this->setCurlOption(CURLOPT_HEADER, 1); - // ask for the response output as the return value - $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1); - // encode - // We manage this ourselves through headers and encoding -// if(function_exists('gzuncompress')){ -// $this->setCurlOption(CURLOPT_ENCODING, 'deflate'); -// } - // persistent connection - if ($this->persistentConnection) { - // I believe the following comment is now bogus, having applied to - // the code when it used CURLOPT_CUSTOMREQUEST to send the request. - // The way we send data, we cannot use persistent connections, since - // there will be some "junk" at the end of our request. - //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true); - $this->persistentConnection = false; - $this->setHeader('Connection', 'close'); - } - // set timeouts - if ($connection_timeout != 0) { - $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout); - } - if ($response_timeout != 0) { - $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout); - } - - if ($this->scheme == 'https') { - $this->debug('set cURL SSL verify options'); - // recent versions of cURL turn on peer/host checking by default, - // while PHP binaries are not compiled with a default location for the - // CA cert bundle, so disable peer/host checking. - //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt'); - $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0); - $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0); - - // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo) - if ($this->authtype == 'certificate') { - $this->debug('set cURL certificate options'); - if (isset($this->certRequest['cainfofile'])) { - $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']); - } - if (isset($this->certRequest['verifypeer'])) { - $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']); - } else { - $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1); - } - if (isset($this->certRequest['verifyhost'])) { - $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']); - } else { - $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1); - } - if (isset($this->certRequest['sslcertfile'])) { - $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']); - } - if (isset($this->certRequest['sslkeyfile'])) { - $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']); - } - if (isset($this->certRequest['passphrase'])) { - $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']); - } - if (isset($this->certRequest['certpassword'])) { - $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']); - } - } - } - if ($this->authtype && ($this->authtype != 'certificate')) { - if ($this->username) { - $this->debug('set cURL username/password'); - $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password"); - } - if ($this->authtype == 'basic') { - $this->debug('set cURL for Basic authentication'); - $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC); - } - if ($this->authtype == 'digest') { - $this->debug('set cURL for digest authentication'); - $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST); - } - if ($this->authtype == 'ntlm') { - $this->debug('set cURL for NTLM authentication'); - $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM); - } - } - if (is_array($this->proxy)) { - $this->debug('set cURL proxy options'); - if ($this->proxy['port'] != '') { - $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']); - } else { - $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']); - } - if ($this->proxy['username'] || $this->proxy['password']) { - $this->debug('set cURL proxy authentication options'); - $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']); - if ($this->proxy['authtype'] == 'basic') { - $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC); - } - if ($this->proxy['authtype'] == 'ntlm') { - $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM); - } - } - } - $this->debug('cURL connection set up'); - return true; - } else { - $this->setError('Unknown scheme ' . $this->scheme); - $this->debug('Unknown scheme ' . $this->scheme); - return false; - } - } - - /** - * sends the SOAP request and gets the SOAP response via HTTP[S] - * - * @param string $data message data - * @param integer $timeout set connection timeout in seconds - * @param integer $response_timeout set response timeout in seconds - * @param array $cookies cookies to send - * @return string data - * @access public - */ - function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) { - - $this->debug('entered send() with data of length: '.strlen($data)); - - $this->tryagain = true; - $tries = 0; - while ($this->tryagain) { - $this->tryagain = false; - if ($tries++ < 2) { - // make connnection - if (!$this->connect($timeout, $response_timeout)){ - return false; - } - - // send request - if (!$this->sendRequest($data, $cookies)){ - return false; - } - - // get response - $respdata = $this->getResponse(); - } else { - $this->setError("Too many tries to get an OK response ($this->response_status_line)"); - } - } - $this->debug('end of send()'); - return $respdata; - } - - - /** - * sends the SOAP request and gets the SOAP response via HTTPS using CURL - * - * @param string $data message data - * @param integer $timeout set connection timeout in seconds - * @param integer $response_timeout set response timeout in seconds - * @param array $cookies cookies to send - * @return string data - * @access public - * @deprecated - */ - function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) { - return $this->send($data, $timeout, $response_timeout, $cookies); - } - - /** - * if authenticating, set user credentials here - * - * @param string $username - * @param string $password - * @param string $authtype (basic|digest|certificate|ntlm) - * @param array $digestRequest (keys must be nonce, nc, realm, qop) - * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) - * @access public - */ - function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) { - $this->debug("setCredentials username=$username authtype=$authtype digestRequest="); - $this->appendDebug($this->varDump($digestRequest)); - $this->debug("certRequest="); - $this->appendDebug($this->varDump($certRequest)); - // cf. RFC 2617 - if ($authtype == 'basic') { - $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password)); - } elseif ($authtype == 'digest') { - if (isset($digestRequest['nonce'])) { - $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1; - - // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html) - - // A1 = unq(username-value) ":" unq(realm-value) ":" passwd - $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password; - - // H(A1) = MD5(A1) - $HA1 = md5($A1); - - // A2 = Method ":" digest-uri-value - $A2 = $this->request_method . ':' . $this->digest_uri; - - // H(A2) - $HA2 = md5($A2); - - // KD(secret, data) = H(concat(secret, ":", data)) - // if qop == auth: - // request-digest = <"> < KD ( H(A1), unq(nonce-value) - // ":" nc-value - // ":" unq(cnonce-value) - // ":" unq(qop-value) - // ":" H(A2) - // ) <"> - // if qop is missing, - // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <"> - - $unhashedDigest = ''; - $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : ''; - $cnonce = $nonce; - if ($digestRequest['qop'] != '') { - $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2; - } else { - $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2; - } - - $hashedDigest = md5($unhashedDigest); - - $opaque = ''; - if (isset($digestRequest['opaque'])) { - $opaque = ', opaque="' . $digestRequest['opaque'] . '"'; - } - - $this->setHeader('Authorization', 'Digest username="' . $username . '", realm="' . $digestRequest['realm'] . '", nonce="' . $nonce . '", uri="' . $this->digest_uri . $opaque . '", cnonce="' . $cnonce . '", nc=' . sprintf("%08x", $digestRequest['nc']) . ', qop="' . $digestRequest['qop'] . '", response="' . $hashedDigest . '"'); - } - } elseif ($authtype == 'certificate') { - $this->certRequest = $certRequest; - $this->debug('Authorization header not set for certificate'); - } elseif ($authtype == 'ntlm') { - // do nothing - $this->debug('Authorization header not set for ntlm'); - } - $this->username = $username; - $this->password = $password; - $this->authtype = $authtype; - $this->digestRequest = $digestRequest; - } - - /** - * set the soapaction value - * - * @param string $soapaction - * @access public - */ - function setSOAPAction($soapaction) { - $this->setHeader('SOAPAction', '"' . $soapaction . '"'); - } - - /** - * use http encoding - * - * @param string $enc encoding style. supported values: gzip, deflate, or both - * @access public - */ - function setEncoding($enc='gzip, deflate') { - if (function_exists('gzdeflate')) { - $this->protocol_version = '1.1'; - $this->setHeader('Accept-Encoding', $enc); - if (!isset($this->outgoing_headers['Connection'])) { - $this->setHeader('Connection', 'close'); - $this->persistentConnection = false; - } - // deprecated as of PHP 5.3.0 - //set_magic_quotes_runtime(0); - $this->encoding = $enc; - } - } - - /** - * set proxy info here - * - * @param string $proxyhost use an empty string to remove proxy - * @param string $proxyport - * @param string $proxyusername - * @param string $proxypassword - * @param string $proxyauthtype (basic|ntlm) - * @access public - */ - function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') { - if ($proxyhost) { - $this->proxy = array( - 'host' => $proxyhost, - 'port' => $proxyport, - 'username' => $proxyusername, - 'password' => $proxypassword, - 'authtype' => $proxyauthtype - ); - if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') { - $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword)); - } - } else { - $this->debug('remove proxy'); - $proxy = null; - unsetHeader('Proxy-Authorization'); - } - } - - - /** - * Test if the given string starts with a header that is to be skipped. - * Skippable headers result from chunked transfer and proxy requests. - * - * @param string $data The string to check. - * @returns boolean Whether a skippable header was found. - * @access private - */ - function isSkippableCurlHeader(&$data) { - $skipHeaders = array( 'HTTP/1.1 100', - 'HTTP/1.0 301', - 'HTTP/1.1 301', - 'HTTP/1.0 302', - 'HTTP/1.1 302', - 'HTTP/1.0 401', - 'HTTP/1.1 401', - 'HTTP/1.0 200 Connection established'); - foreach ($skipHeaders as $hd) { - $prefix = substr($data, 0, strlen($hd)); - if ($prefix == $hd) return true; - } - - return false; - } - - /** - * decode a string that is encoded w/ "chunked' transfer encoding - * as defined in RFC2068 19.4.6 - * - * @param string $buffer - * @param string $lb - * @returns string - * @access public - * @deprecated - */ - function decodeChunked($buffer, $lb){ - // length := 0 - $length = 0; - $new = ''; - - // read chunk-size, chunk-extension (if any) and CRLF - // get the position of the linebreak - $chunkend = strpos($buffer, $lb); - if ($chunkend == FALSE) { - $this->debug('no linebreak found in decodeChunked'); - return $new; - } - $temp = substr($buffer,0,$chunkend); - $chunk_size = hexdec( trim($temp) ); - $chunkstart = $chunkend + strlen($lb); - // while (chunk-size > 0) { - while ($chunk_size > 0) { - $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size"); - $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size); - - // Just in case we got a broken connection - if ($chunkend == FALSE) { - $chunk = substr($buffer,$chunkstart); - // append chunk-data to entity-body - $new .= $chunk; - $length += strlen($chunk); - break; - } - - // read chunk-data and CRLF - $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart); - // append chunk-data to entity-body - $new .= $chunk; - // length := length + chunk-size - $length += strlen($chunk); - // read chunk-size and CRLF - $chunkstart = $chunkend + strlen($lb); - - $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb); - if ($chunkend == FALSE) { - break; //Just in case we got a broken connection - } - $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart); - $chunk_size = hexdec( trim($temp) ); - $chunkstart = $chunkend; - } - return $new; - } - - /** - * Writes the payload, including HTTP headers, to $this->outgoing_payload. - * - * @param string $data HTTP body - * @param string $cookie_str data for HTTP Cookie header - * @return void - * @access private - */ - function buildPayload($data, $cookie_str = '') { - // Note: for cURL connections, $this->outgoing_payload is ignored, - // as is the Content-Length header, but these are still created as - // debugging guides. - - // add content-length header - if ($this->request_method != 'GET') { - $this->setHeader('Content-Length', strlen($data)); - } - - // start building outgoing payload: - if ($this->proxy) { - $uri = $this->url; - } else { - $uri = $this->uri; - } - $req = "$this->request_method $uri HTTP/$this->protocol_version"; - $this->debug("HTTP request: $req"); - $this->outgoing_payload = "$req\r\n"; - - // loop thru headers, serializing - foreach($this->outgoing_headers as $k => $v){ - $hdr = $k.': '.$v; - $this->debug("HTTP header: $hdr"); - $this->outgoing_payload .= "$hdr\r\n"; - } - - // add any cookies - if ($cookie_str != '') { - $hdr = 'Cookie: '.$cookie_str; - $this->debug("HTTP header: $hdr"); - $this->outgoing_payload .= "$hdr\r\n"; - } - - // header/body separator - $this->outgoing_payload .= "\r\n"; - - // add data - $this->outgoing_payload .= $data; - } - - /** - * sends the SOAP request via HTTP[S] - * - * @param string $data message data - * @param array $cookies cookies to send - * @return boolean true if OK, false if problem - * @access private - */ - function sendRequest($data, $cookies = NULL) { - // build cookie string - $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https'))); - - // build payload - $this->buildPayload($data, $cookie_str); - - if ($this->io_method() == 'socket') { - // send payload - if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) { - $this->setError('couldn\'t write message data to socket'); - $this->debug('couldn\'t write message data to socket'); - return false; - } - $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload)); - return true; - } else if ($this->io_method() == 'curl') { - // set payload - // cURL does say this should only be the verb, and in fact it - // turns out that the URI and HTTP version are appended to this, which - // some servers refuse to work with (so we no longer use this method!) - //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload); - $curl_headers = array(); - foreach($this->outgoing_headers as $k => $v){ - if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') { - $this->debug("Skip cURL header $k: $v"); - } else { - $curl_headers[] = "$k: $v"; - } - } - if ($cookie_str != '') { - $curl_headers[] = 'Cookie: ' . $cookie_str; - } - $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers); - $this->debug('set cURL HTTP headers'); - if ($this->request_method == "POST") { - $this->setCurlOption(CURLOPT_POST, 1); - $this->setCurlOption(CURLOPT_POSTFIELDS, $data); - $this->debug('set cURL POST data'); - } else { - } - // insert custom user-set cURL options - foreach ($this->ch_options as $key => $val) { - $this->setCurlOption($key, $val); - } - - $this->debug('set cURL payload'); - return true; - } - } - - /** - * gets the SOAP response via HTTP[S] - * - * @return string the response (also sets member variables like incoming_payload) - * @access private - */ - function getResponse(){ - $this->incoming_payload = ''; - - if ($this->io_method() == 'socket') { - // loop until headers have been retrieved - $data = ''; - while (!isset($lb)){ - - // We might EOF during header read. - if(feof($this->fp)) { - $this->incoming_payload = $data; - $this->debug('found no headers before EOF after length ' . strlen($data)); - $this->debug("received before EOF:\n" . $data); - $this->setError('server failed to send headers'); - return false; - } - - $tmp = fgets($this->fp, 256); - $tmplen = strlen($tmp); - $this->debug("read line of $tmplen bytes: " . trim($tmp)); - - if ($tmplen == 0) { - $this->incoming_payload = $data; - $this->debug('socket read of headers timed out after length ' . strlen($data)); - $this->debug("read before timeout: " . $data); - $this->setError('socket read of headers timed out'); - return false; - } - - $data .= $tmp; - $pos = strpos($data,"\r\n\r\n"); - if($pos > 1){ - $lb = "\r\n"; - } else { - $pos = strpos($data,"\n\n"); - if($pos > 1){ - $lb = "\n"; - } - } - // remove 100 headers - if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) { - unset($lb); - $data = ''; - }// - } - // store header data - $this->incoming_payload .= $data; - $this->debug('found end of headers after length ' . strlen($data)); - // process headers - $header_data = trim(substr($data,0,$pos)); - $header_array = explode($lb,$header_data); - $this->incoming_headers = array(); - $this->incoming_cookies = array(); - foreach($header_array as $header_line){ - $arr = explode(':',$header_line, 2); - if(count($arr) > 1){ - $header_name = strtolower(trim($arr[0])); - $this->incoming_headers[$header_name] = trim($arr[1]); - if ($header_name == 'set-cookie') { - // TODO: allow multiple cookies from parseCookie - $cookie = $this->parseCookie(trim($arr[1])); - if ($cookie) { - $this->incoming_cookies[] = $cookie; - $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']); - } else { - $this->debug('did not find cookie in ' . trim($arr[1])); - } - } - } else if (isset($header_name)) { - // append continuation line to previous header - $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line; - } - } - - // loop until msg has been received - if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') { - $content_length = 2147483647; // ignore any content-length header - $chunked = true; - $this->debug("want to read chunked content"); - } elseif (isset($this->incoming_headers['content-length'])) { - $content_length = $this->incoming_headers['content-length']; - $chunked = false; - $this->debug("want to read content of length $content_length"); - } else { - $content_length = 2147483647; - $chunked = false; - $this->debug("want to read content to EOF"); - } - $data = ''; - do { - if ($chunked) { - $tmp = fgets($this->fp, 256); - $tmplen = strlen($tmp); - $this->debug("read chunk line of $tmplen bytes"); - if ($tmplen == 0) { - $this->incoming_payload = $data; - $this->debug('socket read of chunk length timed out after length ' . strlen($data)); - $this->debug("read before timeout:\n" . $data); - $this->setError('socket read of chunk length timed out'); - return false; - } - $content_length = hexdec(trim($tmp)); - $this->debug("chunk length $content_length"); - } - $strlen = 0; - while (($strlen < $content_length) && (!feof($this->fp))) { - $readlen = min(8192, $content_length - $strlen); - $tmp = fread($this->fp, $readlen); - $tmplen = strlen($tmp); - $this->debug("read buffer of $tmplen bytes"); - if (($tmplen == 0) && (!feof($this->fp))) { - $this->incoming_payload = $data; - $this->debug('socket read of body timed out after length ' . strlen($data)); - $this->debug("read before timeout:\n" . $data); - $this->setError('socket read of body timed out'); - return false; - } - $strlen += $tmplen; - $data .= $tmp; - } - if ($chunked && ($content_length > 0)) { - $tmp = fgets($this->fp, 256); - $tmplen = strlen($tmp); - $this->debug("read chunk terminator of $tmplen bytes"); - if ($tmplen == 0) { - $this->incoming_payload = $data; - $this->debug('socket read of chunk terminator timed out after length ' . strlen($data)); - $this->debug("read before timeout:\n" . $data); - $this->setError('socket read of chunk terminator timed out'); - return false; - } - } - } while ($chunked && ($content_length > 0) && (!feof($this->fp))); - if (feof($this->fp)) { - $this->debug('read to EOF'); - } - $this->debug('read body of length ' . strlen($data)); - $this->incoming_payload .= $data; - $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server'); - - // close filepointer - if( - (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') || - (! $this->persistentConnection) || feof($this->fp)){ - fclose($this->fp); - $this->fp = false; - $this->debug('closed socket'); - } - - // connection was closed unexpectedly - if($this->incoming_payload == ''){ - $this->setError('no response from server'); - return false; - } - - // decode transfer-encoding -// if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){ -// if(!$data = $this->decodeChunked($data, $lb)){ -// $this->setError('Decoding of chunked data failed'); -// return false; -// } - //print "
    \nde-chunked:\n---------------\n$data\n\n---------------\n
    "; - // set decoded payload -// $this->incoming_payload = $header_data.$lb.$lb.$data; -// } - - } else if ($this->io_method() == 'curl') { - // send and receive - $this->debug('send and receive with cURL'); - $this->incoming_payload = curl_exec($this->ch); - $data = $this->incoming_payload; - - $cErr = curl_error($this->ch); - if ($cErr != '') { - $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'
    '; - // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE - foreach(curl_getinfo($this->ch) as $k => $v){ - $err .= "$k: $v
    "; - } - $this->debug($err); - $this->setError($err); - curl_close($this->ch); - return false; - } else { - //echo '
    ';
    -			//var_dump(curl_getinfo($this->ch));
    -			//echo '
    '; - } - // close curl - $this->debug('No cURL error, closing cURL'); - curl_close($this->ch); - - // try removing skippable headers - $savedata = $data; - while ($this->isSkippableCurlHeader($data)) { - $this->debug("Found HTTP header to skip"); - if ($pos = strpos($data,"\r\n\r\n")) { - $data = ltrim(substr($data,$pos)); - } elseif($pos = strpos($data,"\n\n") ) { - $data = ltrim(substr($data,$pos)); - } - } - - if ($data == '') { - // have nothing left; just remove 100 header(s) - $data = $savedata; - while (preg_match('/^HTTP\/1.1 100/',$data)) { - if ($pos = strpos($data,"\r\n\r\n")) { - $data = ltrim(substr($data,$pos)); - } elseif($pos = strpos($data,"\n\n") ) { - $data = ltrim(substr($data,$pos)); - } - } - } - - // separate content from HTTP headers - if ($pos = strpos($data,"\r\n\r\n")) { - $lb = "\r\n"; - } elseif( $pos = strpos($data,"\n\n")) { - $lb = "\n"; - } else { - $this->debug('no proper separation of headers and document'); - $this->setError('no proper separation of headers and document'); - return false; - } - $header_data = trim(substr($data,0,$pos)); - $header_array = explode($lb,$header_data); - $data = ltrim(substr($data,$pos)); - $this->debug('found proper separation of headers and document'); - $this->debug('cleaned data, stringlen: '.strlen($data)); - // clean headers - foreach ($header_array as $header_line) { - $arr = explode(':',$header_line,2); - if(count($arr) > 1){ - $header_name = strtolower(trim($arr[0])); - $this->incoming_headers[$header_name] = trim($arr[1]); - if ($header_name == 'set-cookie') { - // TODO: allow multiple cookies from parseCookie - $cookie = $this->parseCookie(trim($arr[1])); - if ($cookie) { - $this->incoming_cookies[] = $cookie; - $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']); - } else { - $this->debug('did not find cookie in ' . trim($arr[1])); - } - } - } else if (isset($header_name)) { - // append continuation line to previous header - $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line; - } - } - } - - $this->response_status_line = $header_array[0]; - $arr = explode(' ', $this->response_status_line, 3); - $http_version = $arr[0]; - $http_status = intval($arr[1]); - $http_reason = count($arr) > 2 ? $arr[2] : ''; - - // see if we need to resend the request with http digest authentication - if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) { - $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']); - $this->setURL($this->incoming_headers['location']); - $this->tryagain = true; - return false; - } - - // see if we need to resend the request with http digest authentication - if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) { - $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']); - if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) { - $this->debug('Server wants digest authentication'); - // remove "Digest " from our elements - $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']); - - // parse elements into array - $digestElements = explode(',', $digestString); - foreach ($digestElements as $val) { - $tempElement = explode('=', trim($val), 2); - $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]); - } - - // should have (at least) qop, realm, nonce - if (isset($digestRequest['nonce'])) { - $this->setCredentials($this->username, $this->password, 'digest', $digestRequest); - $this->tryagain = true; - return false; - } - } - $this->debug('HTTP authentication failed'); - $this->setError('HTTP authentication failed'); - return false; - } - - if ( - ($http_status >= 300 && $http_status <= 307) || - ($http_status >= 400 && $http_status <= 417) || - ($http_status >= 501 && $http_status <= 505) - ) { - $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)"); - return false; - } - - // decode content-encoding - if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){ - if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){ - // if decoding works, use it. else assume data wasn't gzencoded - if(function_exists('gzinflate')){ - //$timer->setMarker('starting decoding of gzip/deflated content'); - // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress) - // this means there are no Zlib headers, although there should be - $this->debug('The gzinflate function exists'); - $datalen = strlen($data); - if ($this->incoming_headers['content-encoding'] == 'deflate') { - if ($degzdata = @gzinflate($data)) { - $data = $degzdata; - $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes'); - if (strlen($data) < $datalen) { - // test for the case that the payload has been compressed twice - $this->debug('The inflated payload is smaller than the gzipped one; try again'); - if ($degzdata = @gzinflate($data)) { - $data = $degzdata; - $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes'); - } - } - } else { - $this->debug('Error using gzinflate to inflate the payload'); - $this->setError('Error using gzinflate to inflate the payload'); - } - } elseif ($this->incoming_headers['content-encoding'] == 'gzip') { - if ($degzdata = @gzinflate(substr($data, 10))) { // do our best - $data = $degzdata; - $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes'); - if (strlen($data) < $datalen) { - // test for the case that the payload has been compressed twice - $this->debug('The un-gzipped payload is smaller than the gzipped one; try again'); - if ($degzdata = @gzinflate(substr($data, 10))) { - $data = $degzdata; - $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes'); - } - } - } else { - $this->debug('Error using gzinflate to un-gzip the payload'); - $this->setError('Error using gzinflate to un-gzip the payload'); - } - } - //$timer->setMarker('finished decoding of gzip/deflated content'); - //print "\nde-inflated:\n---------------\n$data\n-------------\n"; - // set decoded payload - $this->incoming_payload = $header_data.$lb.$lb.$data; - } else { - $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.'); - $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.'); - } - } else { - $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']); - $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']); - } - } else { - $this->debug('No Content-Encoding header'); - } - - if(strlen($data) == 0){ - $this->debug('no data after headers!'); - $this->setError('no data present after HTTP headers'); - return false; - } - - return $data; - } - - /** - * sets the content-type for the SOAP message to be sent - * - * @param string $type the content type, MIME style - * @param mixed $charset character set used for encoding (or false) - * @access public - */ - function setContentType($type, $charset = false) { - $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : '')); - } - - /** - * specifies that an HTTP persistent connection should be used - * - * @return boolean whether the request was honored by this method. - * @access public - */ - function usePersistentConnection(){ - if (isset($this->outgoing_headers['Accept-Encoding'])) { - return false; - } - $this->protocol_version = '1.1'; - $this->persistentConnection = true; - $this->setHeader('Connection', 'Keep-Alive'); - return true; - } - - /** - * parse an incoming Cookie into it's parts - * - * @param string $cookie_str content of cookie - * @return array with data of that cookie - * @access private - */ - /* - * TODO: allow a Set-Cookie string to be parsed into multiple cookies - */ - function parseCookie($cookie_str) { - $cookie_str = str_replace('; ', ';', $cookie_str) . ';'; - $data = preg_split('/;/', $cookie_str); - $value_str = $data[0]; - - $cookie_param = 'domain='; - $start = strpos($cookie_str, $cookie_param); - if ($start > 0) { - $domain = substr($cookie_str, $start + strlen($cookie_param)); - $domain = substr($domain, 0, strpos($domain, ';')); - } else { - $domain = ''; - } - - $cookie_param = 'expires='; - $start = strpos($cookie_str, $cookie_param); - if ($start > 0) { - $expires = substr($cookie_str, $start + strlen($cookie_param)); - $expires = substr($expires, 0, strpos($expires, ';')); - } else { - $expires = ''; - } - - $cookie_param = 'path='; - $start = strpos($cookie_str, $cookie_param); - if ( $start > 0 ) { - $path = substr($cookie_str, $start + strlen($cookie_param)); - $path = substr($path, 0, strpos($path, ';')); - } else { - $path = '/'; - } - - $cookie_param = ';secure;'; - if (strpos($cookie_str, $cookie_param) !== FALSE) { - $secure = true; - } else { - $secure = false; - } - - $sep_pos = strpos($value_str, '='); - - if ($sep_pos) { - $name = substr($value_str, 0, $sep_pos); - $value = substr($value_str, $sep_pos + 1); - $cookie= array( 'name' => $name, - 'value' => $value, - 'domain' => $domain, - 'path' => $path, - 'expires' => $expires, - 'secure' => $secure - ); - return $cookie; - } - return false; - } - - /** - * sort out cookies for the current request - * - * @param array $cookies array with all cookies - * @param boolean $secure is the send-content secure or not? - * @return string for Cookie-HTTP-Header - * @access private - */ - function getCookiesForRequest($cookies, $secure=false) { - $cookie_str = ''; - if ((! is_null($cookies)) && (is_array($cookies))) { - foreach ($cookies as $cookie) { - if (! is_array($cookie)) { - continue; - } - $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']); - if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) { - if (strtotime($cookie['expires']) <= time()) { - $this->debug('cookie has expired'); - continue; - } - } - if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) { - $domain = preg_quote($cookie['domain']); - if (! preg_match("'.*$domain$'i", $this->host)) { - $this->debug('cookie has different domain'); - continue; - } - } - if ((isset($cookie['path'])) && (! empty($cookie['path']))) { - $path = preg_quote($cookie['path']); - if (! preg_match("'^$path.*'i", $this->path)) { - $this->debug('cookie is for a different path'); - continue; - } - } - if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) { - $this->debug('cookie is secure, transport is not'); - continue; - } - $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; '; - $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']); - } - } - return $cookie_str; - } -} - - -?> \ No newline at end of file diff --git a/lib/nusoap/class.soap_val.php b/lib/nusoap/class.soap_val.php deleted file mode 100644 index 4438f5cff..000000000 --- a/lib/nusoap/class.soap_val.php +++ /dev/null @@ -1,107 +0,0 @@ - -* @version $Id: class.soap_val.php,v 1.11 2007/04/06 13:56:32 snichol Exp $ -* @access public -*/ -class soapval extends nusoap_base { - /** - * The XML element name - * - * @var string - * @access private - */ - var $name; - /** - * The XML type name (string or false) - * - * @var mixed - * @access private - */ - var $type; - /** - * The PHP value - * - * @var mixed - * @access private - */ - var $value; - /** - * The XML element namespace (string or false) - * - * @var mixed - * @access private - */ - var $element_ns; - /** - * The XML type namespace (string or false) - * - * @var mixed - * @access private - */ - var $type_ns; - /** - * The XML element attributes (array or false) - * - * @var mixed - * @access private - */ - var $attributes; - - /** - * constructor - * - * @param string $name optional name - * @param mixed $type optional type name - * @param mixed $value optional value - * @param mixed $element_ns optional namespace of value - * @param mixed $type_ns optional namespace of type - * @param mixed $attributes associative array of attributes to add to element serialization - * @access public - */ - function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) { - parent::nusoap_base(); - $this->name = $name; - $this->type = $type; - $this->value = $value; - $this->element_ns = $element_ns; - $this->type_ns = $type_ns; - $this->attributes = $attributes; - } - - /** - * return serialized value - * - * @param string $use The WSDL use value (encoded|literal) - * @return string XML data - * @access public - */ - function serialize($use='encoded') { - return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true); - } - - /** - * decodes a soapval object into a PHP native type - * - * @return mixed - * @access public - */ - function decode(){ - return $this->value; - } -} - - - - -?> \ No newline at end of file diff --git a/lib/nusoap/class.soapclient.php b/lib/nusoap/class.soapclient.php deleted file mode 100644 index 6944c2aab..000000000 --- a/lib/nusoap/class.soapclient.php +++ /dev/null @@ -1,991 +0,0 @@ -call( string methodname [ ,array parameters] ); -* -* // bye bye client -* unset($soapclient); -* -* @author Dietrich Ayala -* @author Scott Nichol -* @version $Id: class.soapclient.php,v 1.69 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_client extends nusoap_base { - - var $username = ''; // Username for HTTP authentication - var $password = ''; // Password for HTTP authentication - var $authtype = ''; // Type of HTTP authentication - var $certRequest = array(); // Certificate for HTTP SSL authentication - var $requestHeaders = false; // SOAP headers in request (text) - var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text) - var $responseHeader = NULL; // SOAP Header from response (parsed) - var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text) - var $endpoint; - var $forceEndpoint = ''; // overrides WSDL endpoint - var $proxyhost = ''; - var $proxyport = ''; - var $proxyusername = ''; - var $proxypassword = ''; - var $portName = ''; // port name to use in WSDL - var $xml_encoding = ''; // character set encoding of incoming (response) messages - var $http_encoding = false; - var $timeout = 0; // HTTP connection timeout - var $response_timeout = 30; // HTTP response timeout - var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error - var $persistentConnection = false; - var $defaultRpcParams = false; // This is no longer used - var $request = ''; // HTTP request - var $response = ''; // HTTP response - var $responseData = ''; // SOAP payload of response - var $cookies = array(); // Cookies from response or for request - var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode() - var $operations = array(); // WSDL operations, empty for WSDL initialization error - var $curl_options = array(); // User-specified cURL options - var $bindingType = ''; // WSDL operation binding type - var $use_curl = false; // whether to always try to use cURL - - /* - * fault related variables - */ - /** - * @var fault - * @access public - */ - var $fault; - /** - * @var faultcode - * @access public - */ - var $faultcode; - /** - * @var faultstring - * @access public - */ - var $faultstring; - /** - * @var faultdetail - * @access public - */ - var $faultdetail; - - /** - * constructor - * - * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object) - * @param mixed $wsdl optional, set to 'wsdl' or true if using WSDL - * @param string $proxyhost optional - * @param string $proxyport optional - * @param string $proxyusername optional - * @param string $proxypassword optional - * @param integer $timeout set the connection timeout - * @param integer $response_timeout set the response timeout - * @param string $portName optional portName in WSDL document - * @access public - */ - function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = ''){ - parent::nusoap_base(); - $this->endpoint = $endpoint; - $this->proxyhost = $proxyhost; - $this->proxyport = $proxyport; - $this->proxyusername = $proxyusername; - $this->proxypassword = $proxypassword; - $this->timeout = $timeout; - $this->response_timeout = $response_timeout; - $this->portName = $portName; - - $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout"); - $this->appendDebug('endpoint=' . $this->varDump($endpoint)); - - // make values - if($wsdl){ - if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) { - $this->wsdl = $endpoint; - $this->endpoint = $this->wsdl->wsdl; - $this->wsdlFile = $this->endpoint; - $this->debug('existing wsdl instance created from ' . $this->endpoint); - $this->checkWSDL(); - } else { - $this->wsdlFile = $this->endpoint; - $this->wsdl = null; - $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint); - } - $this->endpointType = 'wsdl'; - } else { - $this->debug("instantiate SOAP with endpoint at $endpoint"); - $this->endpointType = 'soap'; - } - } - - /** - * calls method, returns PHP native type - * - * @param string $operation SOAP server URL or path - * @param mixed $params An array, associative or simple, of the parameters - * for the method call, or a string that is the XML - * for the call. For rpc style, this call will - * wrap the XML in a tag named after the method, as - * well as the SOAP Envelope and Body. For document - * style, this will only wrap with the Envelope and Body. - * IMPORTANT: when using an array with document style, - * in which case there - * is really one parameter, the root of the fragment - * used in the call, which encloses what programmers - * normally think of parameters. A parameter array - * *must* include the wrapper. - * @param string $namespace optional method namespace (WSDL can override) - * @param string $soapAction optional SOAPAction value (WSDL can override) - * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array - * @param boolean $rpcParams optional (no longer used) - * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override) - * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override) - * @return mixed response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors - * @access public - */ - function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){ - $this->operation = $operation; - $this->fault = false; - $this->setError(''); - $this->request = ''; - $this->response = ''; - $this->responseData = ''; - $this->faultstring = ''; - $this->faultcode = ''; - $this->opData = array(); - - $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType"); - $this->appendDebug('params=' . $this->varDump($params)); - $this->appendDebug('headers=' . $this->varDump($headers)); - if ($headers) { - $this->requestHeaders = $headers; - } - if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) { - $this->loadWSDL(); - if ($this->getError()) - return false; - } - // serialize parameters - if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){ - // use WSDL for operation - $this->opData = $opData; - $this->debug("found operation"); - $this->appendDebug('opData=' . $this->varDump($opData)); - if (isset($opData['soapAction'])) { - $soapAction = $opData['soapAction']; - } - if (! $this->forceEndpoint) { - $this->endpoint = $opData['endpoint']; - } else { - $this->endpoint = $this->forceEndpoint; - } - $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace; - $style = $opData['style']; - $use = $opData['input']['use']; - // add ns to ns array - if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){ - $nsPrefix = 'ns' . rand(1000, 9999); - $this->wsdl->namespaces[$nsPrefix] = $namespace; - } - $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace); - // serialize payload - if (is_string($params)) { - $this->debug("serializing param string for WSDL operation $operation"); - $payload = $params; - } elseif (is_array($params)) { - $this->debug("serializing param array for WSDL operation $operation"); - $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType); - } else { - $this->debug('params must be array or string'); - $this->setError('params must be array or string'); - return false; - } - $usedNamespaces = $this->wsdl->usedNamespaces; - if (isset($opData['input']['encodingStyle'])) { - $encodingStyle = $opData['input']['encodingStyle']; - } else { - $encodingStyle = ''; - } - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - if ($errstr = $this->wsdl->getError()) { - $this->debug('got wsdl error: '.$errstr); - $this->setError('wsdl error: '.$errstr); - return false; - } - } elseif($this->endpointType == 'wsdl') { - // operation not in WSDL - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->setError('operation '.$operation.' not present in WSDL.'); - $this->debug("operation '$operation' not present in WSDL."); - return false; - } else { - // no WSDL - //$this->namespaces['ns1'] = $namespace; - $nsPrefix = 'ns' . rand(1000, 9999); - // serialize - $payload = ''; - if (is_string($params)) { - $this->debug("serializing param string for operation $operation"); - $payload = $params; - } elseif (is_array($params)) { - $this->debug("serializing param array for operation $operation"); - foreach($params as $k => $v){ - $payload .= $this->serialize_val($v,$k,false,false,false,false,$use); - } - } else { - $this->debug('params must be array or string'); - $this->setError('params must be array or string'); - return false; - } - $usedNamespaces = array(); - if ($use == 'encoded') { - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - } else { - $encodingStyle = ''; - } - } - // wrap RPC calls with method element - if ($style == 'rpc') { - if ($use == 'literal') { - $this->debug("wrapping RPC request with literal method element"); - if ($namespace) { - // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace - $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" . - $payload . - ""; - } else { - $payload = "<$operation>" . $payload . ""; - } - } else { - $this->debug("wrapping RPC request with encoded method element"); - if ($namespace) { - $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" . - $payload . - ""; - } else { - $payload = "<$operation>" . - $payload . - ""; - } - } - } - // serialize envelope - $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle); - $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle"); - $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000)); - // send - $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout); - if($errstr = $this->getError()){ - $this->debug('Error: '.$errstr); - return false; - } else { - $this->return = $return; - $this->debug('sent message successfully and got a(n) '.gettype($return)); - $this->appendDebug('return=' . $this->varDump($return)); - - // fault? - if(is_array($return) && isset($return['faultcode'])){ - $this->debug('got fault'); - $this->setError($return['faultcode'].': '.$return['faultstring']); - $this->fault = true; - foreach($return as $k => $v){ - $this->$k = $v; - $this->debug("$k = $v
    "); - } - return $return; - } elseif ($style == 'document') { - // NOTE: if the response is defined to have multiple parts (i.e. unwrapped), - // we are only going to return the first part here...sorry about that - return $return; - } else { - // array of return values - if(is_array($return)){ - // multiple 'out' parameters, which we return wrapped up - // in the array - if(sizeof($return) > 1){ - return $return; - } - // single 'out' parameter (normally the return value) - $return = array_shift($return); - $this->debug('return shifted value: '); - $this->appendDebug($this->varDump($return)); - return $return; - // nothing returned (ie, echoVoid) - } else { - return ""; - } - } - } - } - - /** - * check WSDL passed as an instance or pulled from an endpoint - * - * @access private - */ - function checkWSDL() { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->debug('checkWSDL'); - // catch errors - if ($errstr = $this->wsdl->getError()) { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->debug('got wsdl error: '.$errstr); - $this->setError('wsdl error: '.$errstr); - } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->bindingType = 'soap'; - $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType); - } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->bindingType = 'soap12'; - $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType); - $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************'); - } else { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->debug('getOperations returned false'); - $this->setError('no operations defined in the WSDL document!'); - } - } - - /** - * instantiate wsdl object and parse wsdl file - * - * @access public - */ - function loadWSDL() { - $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile); - $this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl); - $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest); - $this->wsdl->fetchWSDL($this->wsdlFile); - $this->checkWSDL(); - } - - /** - * get available data pertaining to an operation - * - * @param string $operation operation name - * @return array array of data pertaining to the operation - * @access public - */ - function getOperationData($operation){ - if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) { - $this->loadWSDL(); - if ($this->getError()) - return false; - } - if(isset($this->operations[$operation])){ - return $this->operations[$operation]; - } - $this->debug("No data for operation: $operation"); - } - - /** - * send the SOAP message - * - * Note: if the operation has multiple return values - * the return value of this method will be an array - * of those values. - * - * @param string $msg a SOAPx4 soapmsg object - * @param string $soapaction SOAPAction value - * @param integer $timeout set connection timeout in seconds - * @param integer $response_timeout set response timeout in seconds - * @return mixed native PHP types. - * @access private - */ - function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) { - $this->checkCookies(); - // detect transport - switch(true){ - // http(s) - case preg_match('/^http/',$this->endpoint): - $this->debug('transporting via HTTP'); - if($this->persistentConnection == true && is_object($this->persistentConnection)){ - $http =& $this->persistentConnection; - } else { - $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl); - if ($this->persistentConnection) { - $http->usePersistentConnection(); - } - } - $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset()); - $http->setSOAPAction($soapaction); - if($this->proxyhost && $this->proxyport){ - $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword); - } - if($this->authtype != '') { - $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest); - } - if($this->http_encoding != ''){ - $http->setEncoding($this->http_encoding); - } - $this->debug('sending message, length='.strlen($msg)); - if(preg_match('/^http:/',$this->endpoint)){ - //if(strpos($this->endpoint,'http:')){ - $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies); - } elseif(preg_match('/^https/',$this->endpoint)){ - //} elseif(strpos($this->endpoint,'https:')){ - //if(phpversion() == '4.3.0-dev'){ - //$response = $http->send($msg,$timeout,$response_timeout); - //$this->request = $http->outgoing_payload; - //$this->response = $http->incoming_payload; - //} else - $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies); - } else { - $this->setError('no http/s in endpoint url'); - } - $this->request = $http->outgoing_payload; - $this->response = $http->incoming_payload; - $this->appendDebug($http->getDebug()); - $this->UpdateCookies($http->incoming_cookies); - - // save transport object if using persistent connections - if ($this->persistentConnection) { - $http->clearDebug(); - if (!is_object($this->persistentConnection)) { - $this->persistentConnection = $http; - } - } - - if($err = $http->getError()){ - $this->setError('HTTP Error: '.$err); - return false; - } elseif($this->getError()){ - return false; - } else { - $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']); - return $this->parseResponse($http->incoming_headers, $this->responseData); - } - break; - default: - $this->setError('no transport found, or selected transport is not yet supported!'); - return false; - break; - } - } - - /** - * processes SOAP message returned from server - * - * @param array $headers The HTTP headers - * @param string $data unprocessed response data from server - * @return mixed value of the message, decoded into a PHP type - * @access private - */ - function parseResponse($headers, $data) { - $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:'); - $this->appendDebug($this->varDump($headers)); - if (!isset($headers['content-type'])) { - $this->setError('Response not of type text/xml (no content-type header)'); - return false; - } - if (!strstr($headers['content-type'], 'text/xml')) { - $this->setError('Response not of type text/xml: ' . $headers['content-type']); - return false; - } - if (strpos($headers['content-type'], '=')) { - $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1)); - $this->debug('Got response encoding: ' . $enc); - if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){ - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser'); - $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8); - // add parser debug data to our debug - $this->appendDebug($parser->getDebug()); - // if parse errors - if($errstr = $parser->getError()){ - $this->setError( $errstr); - // destroy the parser object - unset($parser); - return false; - } else { - // get SOAP headers - $this->responseHeaders = $parser->getHeaders(); - // get SOAP headers - $this->responseHeader = $parser->get_soapheader(); - // get decoded message - $return = $parser->get_soapbody(); - // add document for doclit support - $this->document = $parser->document; - // destroy the parser object - unset($parser); - // return decode message - return $return; - } - } - - /** - * sets user-specified cURL options - * - * @param mixed $option The cURL option (always integer?) - * @param mixed $value The cURL option value - * @access public - */ - function setCurlOption($option, $value) { - $this->debug("setCurlOption option=$option, value="); - $this->appendDebug($this->varDump($value)); - $this->curl_options[$option] = $value; - } - - /** - * sets the SOAP endpoint, which can override WSDL - * - * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override - * @access public - */ - function setEndpoint($endpoint) { - $this->debug("setEndpoint(\"$endpoint\")"); - $this->forceEndpoint = $endpoint; - } - - /** - * set the SOAP headers - * - * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers - * @access public - */ - function setHeaders($headers){ - $this->debug("setHeaders headers="); - $this->appendDebug($this->varDump($headers)); - $this->requestHeaders = $headers; - } - - /** - * get the SOAP response headers (namespace resolution incomplete) - * - * @return string - * @access public - */ - function getHeaders(){ - return $this->responseHeaders; - } - - /** - * get the SOAP response Header (parsed) - * - * @return mixed - * @access public - */ - function getHeader(){ - return $this->responseHeader; - } - - /** - * set proxy info here - * - * @param string $proxyhost - * @param string $proxyport - * @param string $proxyusername - * @param string $proxypassword - * @access public - */ - function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') { - $this->proxyhost = $proxyhost; - $this->proxyport = $proxyport; - $this->proxyusername = $proxyusername; - $this->proxypassword = $proxypassword; - } - - /** - * if authenticating, set user credentials here - * - * @param string $username - * @param string $password - * @param string $authtype (basic|digest|certificate|ntlm) - * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) - * @access public - */ - function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) { - $this->debug("setCredentials username=$username authtype=$authtype certRequest="); - $this->appendDebug($this->varDump($certRequest)); - $this->username = $username; - $this->password = $password; - $this->authtype = $authtype; - $this->certRequest = $certRequest; - } - - /** - * use HTTP encoding - * - * @param string $enc HTTP encoding - * @access public - */ - function setHTTPEncoding($enc='gzip, deflate'){ - $this->debug("setHTTPEncoding(\"$enc\")"); - $this->http_encoding = $enc; - } - - /** - * Set whether to try to use cURL connections if possible - * - * @param boolean $use Whether to try to use cURL - * @access public - */ - function setUseCURL($use) { - $this->debug("setUseCURL($use)"); - $this->use_curl = $use; - } - - /** - * use HTTP persistent connections if possible - * - * @access public - */ - function useHTTPPersistentConnection(){ - $this->debug("useHTTPPersistentConnection"); - $this->persistentConnection = true; - } - - /** - * gets the default RPC parameter setting. - * If true, default is that call params are like RPC even for document style. - * Each call() can override this value. - * - * This is no longer used. - * - * @return boolean - * @access public - * @deprecated - */ - function getDefaultRpcParams() { - return $this->defaultRpcParams; - } - - /** - * sets the default RPC parameter setting. - * If true, default is that call params are like RPC even for document style - * Each call() can override this value. - * - * This is no longer used. - * - * @param boolean $rpcParams - * @access public - * @deprecated - */ - function setDefaultRpcParams($rpcParams) { - $this->defaultRpcParams = $rpcParams; - } - - /** - * dynamically creates an instance of a proxy class, - * allowing user to directly call methods from wsdl - * - * @return object soap_proxy object - * @access public - */ - function getProxy() { - $r = rand(); - $evalStr = $this->_getProxyClassCode($r); - //$this->debug("proxy class: $evalStr"); - if ($this->getError()) { - $this->debug("Error from _getProxyClassCode, so return NULL"); - return null; - } - // eval the class - eval($evalStr); - // instantiate proxy object - eval("\$proxy = new nusoap_proxy_$r('');"); - // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice - $proxy->endpointType = 'wsdl'; - $proxy->wsdlFile = $this->wsdlFile; - $proxy->wsdl = $this->wsdl; - $proxy->operations = $this->operations; - $proxy->defaultRpcParams = $this->defaultRpcParams; - // transfer other state - $proxy->soap_defencoding = $this->soap_defencoding; - $proxy->username = $this->username; - $proxy->password = $this->password; - $proxy->authtype = $this->authtype; - $proxy->certRequest = $this->certRequest; - $proxy->requestHeaders = $this->requestHeaders; - $proxy->endpoint = $this->endpoint; - $proxy->forceEndpoint = $this->forceEndpoint; - $proxy->proxyhost = $this->proxyhost; - $proxy->proxyport = $this->proxyport; - $proxy->proxyusername = $this->proxyusername; - $proxy->proxypassword = $this->proxypassword; - $proxy->http_encoding = $this->http_encoding; - $proxy->timeout = $this->timeout; - $proxy->response_timeout = $this->response_timeout; - $proxy->persistentConnection = &$this->persistentConnection; - $proxy->decode_utf8 = $this->decode_utf8; - $proxy->curl_options = $this->curl_options; - $proxy->bindingType = $this->bindingType; - $proxy->use_curl = $this->use_curl; - return $proxy; - } - - /** - * dynamically creates proxy class code - * - * @return string PHP/NuSOAP code for the proxy class - * @access private - */ - function _getProxyClassCode($r) { - $this->debug("in getProxy endpointType=$this->endpointType"); - $this->appendDebug("wsdl=" . $this->varDump($this->wsdl)); - if ($this->endpointType != 'wsdl') { - $evalStr = 'A proxy can only be created for a WSDL client'; - $this->setError($evalStr); - $evalStr = "echo \"$evalStr\";"; - return $evalStr; - } - if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) { - $this->loadWSDL(); - if ($this->getError()) { - return "echo \"" . $this->getError() . "\";"; - } - } - $evalStr = ''; - foreach ($this->operations as $operation => $opData) { - if ($operation != '') { - // create param string and param comment string - if (sizeof($opData['input']['parts']) > 0) { - $paramStr = ''; - $paramArrayStr = ''; - $paramCommentStr = ''; - foreach ($opData['input']['parts'] as $name => $type) { - $paramStr .= "\$$name, "; - $paramArrayStr .= "'$name' => \$$name, "; - $paramCommentStr .= "$type \$$name, "; - } - $paramStr = substr($paramStr, 0, strlen($paramStr)-2); - $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2); - $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2); - } else { - $paramStr = ''; - $paramArrayStr = ''; - $paramCommentStr = 'void'; - } - $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace']; - $evalStr .= "// $paramCommentStr - function " . str_replace('.', '__', $operation) . "($paramStr) { - \$params = array($paramArrayStr); - return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."'); - } - "; - unset($paramStr); - unset($paramCommentStr); - } - } - $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client { - '.$evalStr.' -}'; - return $evalStr; - } - - /** - * dynamically creates proxy class code - * - * @return string PHP/NuSOAP code for the proxy class - * @access public - */ - function getProxyClassCode() { - $r = rand(); - return $this->_getProxyClassCode($r); - } - - /** - * gets the HTTP body for the current request. - * - * @param string $soapmsg The SOAP payload - * @return string The HTTP body, which includes the SOAP payload - * @access private - */ - function getHTTPBody($soapmsg) { - return $soapmsg; - } - - /** - * gets the HTTP content type for the current request. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type for the current request. - * @access private - */ - function getHTTPContentType() { - return 'text/xml'; - } - - /** - * gets the HTTP content type charset for the current request. - * returns false for non-text content types. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type charset for the current request. - * @access private - */ - function getHTTPContentTypeCharset() { - return $this->soap_defencoding; - } - - /* - * whether or not parser should decode utf8 element content - * - * @return always returns true - * @access public - */ - function decodeUTF8($bool){ - $this->decode_utf8 = $bool; - return true; - } - - /** - * adds a new Cookie into $this->cookies array - * - * @param string $name Cookie Name - * @param string $value Cookie Value - * @return boolean if cookie-set was successful returns true, else false - * @access public - */ - function setCookie($name, $value) { - if (strlen($name) == 0) { - return false; - } - $this->cookies[] = array('name' => $name, 'value' => $value); - return true; - } - - /** - * gets all Cookies - * - * @return array with all internal cookies - * @access public - */ - function getCookies() { - return $this->cookies; - } - - /** - * checks all Cookies and delete those which are expired - * - * @return boolean always return true - * @access private - */ - function checkCookies() { - if (sizeof($this->cookies) == 0) { - return true; - } - $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies'); - $curr_cookies = $this->cookies; - $this->cookies = array(); - foreach ($curr_cookies as $cookie) { - if (! is_array($cookie)) { - $this->debug('Remove cookie that is not an array'); - continue; - } - if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) { - if (strtotime($cookie['expires']) > time()) { - $this->cookies[] = $cookie; - } else { - $this->debug('Remove expired cookie ' . $cookie['name']); - } - } else { - $this->cookies[] = $cookie; - } - } - $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array'); - return true; - } - - /** - * updates the current cookies with a new set - * - * @param array $cookies new cookies with which to update current ones - * @return boolean always return true - * @access private - */ - function UpdateCookies($cookies) { - if (sizeof($this->cookies) == 0) { - // no existing cookies: take whatever is new - if (sizeof($cookies) > 0) { - $this->debug('Setting new cookie(s)'); - $this->cookies = $cookies; - } - return true; - } - if (sizeof($cookies) == 0) { - // no new cookies: keep what we've got - return true; - } - // merge - foreach ($cookies as $newCookie) { - if (!is_array($newCookie)) { - continue; - } - if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) { - continue; - } - $newName = $newCookie['name']; - - $found = false; - for ($i = 0; $i < count($this->cookies); $i++) { - $cookie = $this->cookies[$i]; - if (!is_array($cookie)) { - continue; - } - if (!isset($cookie['name'])) { - continue; - } - if ($newName != $cookie['name']) { - continue; - } - $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN'; - $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN'; - if ($newDomain != $domain) { - continue; - } - $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH'; - $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH'; - if ($newPath != $path) { - continue; - } - $this->cookies[$i] = $newCookie; - $found = true; - $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']); - break; - } - if (! $found) { - $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']); - $this->cookies[] = $newCookie; - } - } - return true; - } -} - -if (!extension_loaded('soap')) { - /** - * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded. - */ - class soapclient extends nusoap_client { - } -} -?> diff --git a/lib/nusoap/class.wsdl.php b/lib/nusoap/class.wsdl.php deleted file mode 100644 index 62f98243c..000000000 --- a/lib/nusoap/class.wsdl.php +++ /dev/null @@ -1,1938 +0,0 @@ - -* @author Scott Nichol -* @version $Id: class.wsdl.php,v 1.76 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class wsdl extends nusoap_base { - // URL or filename of the root of this WSDL - var $wsdl; - // define internal arrays of bindings, ports, operations, messages, etc. - var $schemas = array(); - var $currentSchema; - var $message = array(); - var $complexTypes = array(); - var $messages = array(); - var $currentMessage; - var $currentOperation; - var $portTypes = array(); - var $currentPortType; - var $bindings = array(); - var $currentBinding; - var $ports = array(); - var $currentPort; - var $opData = array(); - var $status = ''; - var $documentation = false; - var $endpoint = ''; - // array of wsdl docs to import - var $import = array(); - // parser vars - var $parser; - var $position = 0; - var $depth = 0; - var $depth_array = array(); - // for getting wsdl - var $proxyhost = ''; - var $proxyport = ''; - var $proxyusername = ''; - var $proxypassword = ''; - var $timeout = 0; - var $response_timeout = 30; - var $curl_options = array(); // User-specified cURL options - var $use_curl = false; // whether to always try to use cURL - // for HTTP authentication - var $username = ''; // Username for HTTP authentication - var $password = ''; // Password for HTTP authentication - var $authtype = ''; // Type of HTTP authentication - var $certRequest = array(); // Certificate for HTTP SSL authentication - - /** - * constructor - * - * @param string $wsdl WSDL document URL - * @param string $proxyhost - * @param string $proxyport - * @param string $proxyusername - * @param string $proxypassword - * @param integer $timeout set the connection timeout - * @param integer $response_timeout set the response timeout - * @param array $curl_options user-specified cURL options - * @param boolean $use_curl try to use cURL - * @access public - */ - function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){ - parent::nusoap_base(); - $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout"); - $this->proxyhost = $proxyhost; - $this->proxyport = $proxyport; - $this->proxyusername = $proxyusername; - $this->proxypassword = $proxypassword; - $this->timeout = $timeout; - $this->response_timeout = $response_timeout; - if (is_array($curl_options)) - $this->curl_options = $curl_options; - $this->use_curl = $use_curl; - $this->fetchWSDL($wsdl); - } - - /** - * fetches the WSDL document and parses it - * - * @access public - */ - function fetchWSDL($wsdl) { - $this->debug("parse and process WSDL path=$wsdl"); - $this->wsdl = $wsdl; - // parse wsdl file - if ($this->wsdl != "") { - $this->parseWSDL($this->wsdl); - } - // imports - // TODO: handle imports more properly, grabbing them in-line and nesting them - $imported_urls = array(); - $imported = 1; - while ($imported > 0) { - $imported = 0; - // Schema imports - foreach ($this->schemas as $ns => $list) { - foreach ($list as $ilist => $xs) { - $wsdlparts = parse_url($this->wsdl); // this is bogusly simple! - foreach ($xs->imports as $ns2 => $list2) { - for ($ii = 0; $ii < count($list2); $ii++) { - if (! $list2[$ii]['loaded']) { - $this->schemas[$ns][$ilist]->imports[$ns2][$ii]['loaded'] = true; - $url = $list2[$ii]['location']; - if ($url != '') { - $urlparts = parse_url($url); - if (!isset($urlparts['host'])) { - $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') . - substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path']; - } - if (! in_array($url, $imported_urls)) { - $this->parseWSDL($url); - $imported++; - $imported_urls[] = $url; - } - } else { - $this->debug("Unexpected scenario: empty URL for unloaded import"); - } - } - } - } - } - } - // WSDL imports - $wsdlparts = parse_url($this->wsdl); // this is bogusly simple! - foreach ($this->import as $ns => $list) { - for ($ii = 0; $ii < count($list); $ii++) { - if (! $list[$ii]['loaded']) { - $this->import[$ns][$ii]['loaded'] = true; - $url = $list[$ii]['location']; - if ($url != '') { - $urlparts = parse_url($url); - if (!isset($urlparts['host'])) { - $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') . - substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path']; - } - if (! in_array($url, $imported_urls)) { - $this->parseWSDL($url); - $imported++; - $imported_urls[] = $url; - } - } else { - $this->debug("Unexpected scenario: empty URL for unloaded import"); - } - } - } - } - } - // add new data to operation data - foreach($this->bindings as $binding => $bindingData) { - if (isset($bindingData['operations']) && is_array($bindingData['operations'])) { - foreach($bindingData['operations'] as $operation => $data) { - $this->debug('post-parse data gathering for ' . $operation); - $this->bindings[$binding]['operations'][$operation]['input'] = - isset($this->bindings[$binding]['operations'][$operation]['input']) ? - array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) : - $this->portTypes[ $bindingData['portType'] ][$operation]['input']; - $this->bindings[$binding]['operations'][$operation]['output'] = - isset($this->bindings[$binding]['operations'][$operation]['output']) ? - array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) : - $this->portTypes[ $bindingData['portType'] ][$operation]['output']; - if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){ - $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ]; - } - if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){ - $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ]; - } - // Set operation style if necessary, but do not override one already provided - if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) { - $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style']; - } - $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : ''; - $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : ''; - $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : ''; - } - } - } - } - - /** - * parses the wsdl document - * - * @param string $wsdl path or URL - * @access private - */ - function parseWSDL($wsdl = '') { - $this->debug("parse WSDL at path=$wsdl"); - - if ($wsdl == '') { - $this->debug('no wsdl passed to parseWSDL()!!'); - $this->setError('no wsdl passed to parseWSDL()!!'); - return false; - } - - // parse $wsdl for url format - $wsdl_props = parse_url($wsdl); - - if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) { - $this->debug('getting WSDL http(s) URL ' . $wsdl); - // get wsdl - $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl); - $tr->request_method = 'GET'; - $tr->useSOAPAction = false; - if($this->proxyhost && $this->proxyport){ - $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword); - } - if ($this->authtype != '') { - $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest); - } - $tr->setEncoding('gzip, deflate'); - $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout); - //$this->debug("WSDL request\n" . $tr->outgoing_payload); - //$this->debug("WSDL response\n" . $tr->incoming_payload); - $this->appendDebug($tr->getDebug()); - // catch errors - if($err = $tr->getError() ){ - $errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err; - $this->debug($errstr); - $this->setError($errstr); - unset($tr); - return false; - } - unset($tr); - $this->debug("got WSDL URL"); - } else { - // $wsdl is not http(s), so treat it as a file URL or plain file path - if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) { - $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path']; - } else { - $path = $wsdl; - } - $this->debug('getting WSDL file ' . $path); - if ($fp = @fopen($path, 'r')) { - $wsdl_string = ''; - while ($data = fread($fp, 32768)) { - $wsdl_string .= $data; - } - fclose($fp); - } else { - $errstr = "Bad path to WSDL file $path"; - $this->debug($errstr); - $this->setError($errstr); - return false; - } - } - $this->debug('Parse WSDL'); - // end new code added - // Create an XML parser. - $this->parser = xml_parser_create(); - // Set the options for parsing the XML data. - // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); - xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); - // Set the object for the parser. - xml_set_object($this->parser, $this); - // Set the element handlers for the parser. - xml_set_element_handler($this->parser, 'start_element', 'end_element'); - xml_set_character_data_handler($this->parser, 'character_data'); - // Parse the XML file. - if (!xml_parse($this->parser, $wsdl_string, true)) { - // Display an error message. - $errstr = sprintf( - 'XML error parsing WSDL from %s on line %d: %s', - $wsdl, - xml_get_current_line_number($this->parser), - xml_error_string(xml_get_error_code($this->parser)) - ); - $this->debug($errstr); - $this->debug("XML payload:\n" . $wsdl_string); - $this->setError($errstr); - return false; - } - // free the parser - xml_parser_free($this->parser); - $this->debug('Parsing WSDL done'); - // catch wsdl parse errors - if($this->getError()){ - return false; - } - return true; - } - - /** - * start-element handler - * - * @param string $parser XML parser object - * @param string $name element name - * @param string $attrs associative array of attributes - * @access private - */ - function start_element($parser, $name, $attrs) - { - if ($this->status == 'schema') { - $this->currentSchema->schemaStartElement($parser, $name, $attrs); - $this->appendDebug($this->currentSchema->getDebug()); - $this->currentSchema->clearDebug(); - } elseif (preg_match('/schema$/', $name)) { - $this->debug('Parsing WSDL schema'); - // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")"); - $this->status = 'schema'; - $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces); - $this->currentSchema->schemaStartElement($parser, $name, $attrs); - $this->appendDebug($this->currentSchema->getDebug()); - $this->currentSchema->clearDebug(); - } else { - // position in the total number of elements, starting from 0 - $pos = $this->position++; - $depth = $this->depth++; - // set self as current value for this depth - $this->depth_array[$depth] = $pos; - $this->message[$pos] = array('cdata' => ''); - // process attributes - if (count($attrs) > 0) { - // register namespace declarations - foreach($attrs as $k => $v) { - if (preg_match('/^xmlns/',$k)) { - if ($ns_prefix = substr(strrchr($k, ':'), 1)) { - $this->namespaces[$ns_prefix] = $v; - } else { - $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v; - } - if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') { - $this->XMLSchemaVersion = $v; - $this->namespaces['xsi'] = $v . '-instance'; - } - } - } - // expand each attribute prefix to its namespace - foreach($attrs as $k => $v) { - $k = strpos($k, ':') ? $this->expandQname($k) : $k; - if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') { - $v = strpos($v, ':') ? $this->expandQname($v) : $v; - } - $eAttrs[$k] = $v; - } - $attrs = $eAttrs; - } else { - $attrs = array(); - } - // get element prefix, namespace and name - if (preg_match('/:/', $name)) { - // get ns prefix - $prefix = substr($name, 0, strpos($name, ':')); - // get ns - $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : ''; - // get unqualified name - $name = substr(strstr($name, ':'), 1); - } - // process attributes, expanding any prefixes to namespaces - // find status, register data - switch ($this->status) { - case 'message': - if ($name == 'part') { - if (isset($attrs['type'])) { - $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs)); - $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type']; - } - if (isset($attrs['element'])) { - $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs)); - $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^'; - } - } - break; - case 'portType': - switch ($name) { - case 'operation': - $this->currentPortOperation = $attrs['name']; - $this->debug("portType $this->currentPortType operation: $this->currentPortOperation"); - if (isset($attrs['parameterOrder'])) { - $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder']; - } - break; - case 'documentation': - $this->documentation = true; - break; - // merge input/output data - default: - $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : ''; - $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m; - break; - } - break; - case 'binding': - switch ($name) { - case 'binding': - // get ns prefix - if (isset($attrs['style'])) { - $this->bindings[$this->currentBinding]['prefix'] = $prefix; - } - $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs); - break; - case 'header': - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs; - break; - case 'operation': - if (isset($attrs['soapAction'])) { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction']; - } - if (isset($attrs['style'])) { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style']; - } - if (isset($attrs['name'])) { - $this->currentOperation = $attrs['name']; - $this->debug("current binding operation: $this->currentOperation"); - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name']; - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding; - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : ''; - } - break; - case 'input': - $this->opStatus = 'input'; - break; - case 'output': - $this->opStatus = 'output'; - break; - case 'body': - if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs); - } else { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs; - } - break; - } - break; - case 'service': - switch ($name) { - case 'port': - $this->currentPort = $attrs['name']; - $this->debug('current port: ' . $this->currentPort); - $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']); - - break; - case 'address': - $this->ports[$this->currentPort]['location'] = $attrs['location']; - $this->ports[$this->currentPort]['bindingType'] = $namespace; - $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace; - $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location']; - break; - } - break; - } - // set status - switch ($name) { - case 'import': - if (isset($attrs['location'])) { - $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false); - $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')'); - } else { - $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true); - if (! $this->getPrefixFromNamespace($attrs['namespace'])) { - $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace']; - } - $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')'); - } - break; - //wait for schema - //case 'types': - // $this->status = 'schema'; - // break; - case 'message': - $this->status = 'message'; - $this->messages[$attrs['name']] = array(); - $this->currentMessage = $attrs['name']; - break; - case 'portType': - $this->status = 'portType'; - $this->portTypes[$attrs['name']] = array(); - $this->currentPortType = $attrs['name']; - break; - case "binding": - if (isset($attrs['name'])) { - // get binding name - if (strpos($attrs['name'], ':')) { - $this->currentBinding = $this->getLocalPart($attrs['name']); - } else { - $this->currentBinding = $attrs['name']; - } - $this->status = 'binding'; - $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']); - $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']); - } - break; - case 'service': - $this->serviceName = $attrs['name']; - $this->status = 'service'; - $this->debug('current service: ' . $this->serviceName); - break; - case 'definitions': - foreach ($attrs as $name => $value) { - $this->wsdl_info[$name] = $value; - } - break; - } - } - } - - /** - * end-element handler - * - * @param string $parser XML parser object - * @param string $name element name - * @access private - */ - function end_element($parser, $name){ - // unset schema status - if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) { - $this->status = ""; - $this->appendDebug($this->currentSchema->getDebug()); - $this->currentSchema->clearDebug(); - $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema; - $this->debug('Parsing WSDL schema done'); - } - if ($this->status == 'schema') { - $this->currentSchema->schemaEndElement($parser, $name); - } else { - // bring depth down a notch - $this->depth--; - } - // end documentation - if ($this->documentation) { - //TODO: track the node to which documentation should be assigned; it can be a part, message, etc. - //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation; - $this->documentation = false; - } - } - - /** - * element content handler - * - * @param string $parser XML parser object - * @param string $data element content - * @access private - */ - function character_data($parser, $data) - { - $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0; - if (isset($this->message[$pos]['cdata'])) { - $this->message[$pos]['cdata'] .= $data; - } - if ($this->documentation) { - $this->documentation .= $data; - } - } - - /** - * if authenticating, set user credentials here - * - * @param string $username - * @param string $password - * @param string $authtype (basic|digest|certificate|ntlm) - * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) - * @access public - */ - function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) { - $this->debug("setCredentials username=$username authtype=$authtype certRequest="); - $this->appendDebug($this->varDump($certRequest)); - $this->username = $username; - $this->password = $password; - $this->authtype = $authtype; - $this->certRequest = $certRequest; - } - - function getBindingData($binding) - { - if (is_array($this->bindings[$binding])) { - return $this->bindings[$binding]; - } - } - - /** - * returns an assoc array of operation names => operation data - * - * @param string $portName WSDL port name - * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported) - * @return array - * @access public - */ - function getOperations($portName = '', $bindingType = 'soap') { - $ops = array(); - if ($bindingType == 'soap') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; - } elseif ($bindingType == 'soap12') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - } else { - $this->debug("getOperations bindingType $bindingType may not be supported"); - } - $this->debug("getOperations for port '$portName' bindingType $bindingType"); - // loop thru ports - foreach($this->ports as $port => $portData) { - $this->debug("getOperations checking port $port bindingType " . $portData['bindingType']); - if ($portName == '' || $port == $portName) { - // binding type of port matches parameter - if ($portData['bindingType'] == $bindingType) { - $this->debug("getOperations found port $port bindingType $bindingType"); - //$this->debug("port data: " . $this->varDump($portData)); - //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ])); - // merge bindings - if (isset($this->bindings[ $portData['binding'] ]['operations'])) { - $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']); - } - } - } - } - if (count($ops) == 0) { - $this->debug("getOperations found no operations for port '$portName' bindingType $bindingType"); - } - return $ops; - } - - /** - * returns an associative array of data necessary for calling an operation - * - * @param string $operation name of operation - * @param string $bindingType type of binding eg: soap, soap12 - * @return array - * @access public - */ - function getOperationData($operation, $bindingType = 'soap') - { - if ($bindingType == 'soap') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; - } elseif ($bindingType == 'soap12') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - } - // loop thru ports - foreach($this->ports as $port => $portData) { - // binding type of port matches parameter - if ($portData['bindingType'] == $bindingType) { - // get binding - //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) { - foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) { - // note that we could/should also check the namespace here - if ($operation == $bOperation) { - $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation]; - return $opData; - } - } - } - } - } - - /** - * returns an associative array of data necessary for calling an operation - * - * @param string $soapAction soapAction for operation - * @param string $bindingType type of binding eg: soap, soap12 - * @return array - * @access public - */ - function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') { - if ($bindingType == 'soap') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; - } elseif ($bindingType == 'soap12') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - } - // loop thru ports - foreach($this->ports as $port => $portData) { - // binding type of port matches parameter - if ($portData['bindingType'] == $bindingType) { - // loop through operations for the binding - foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) { - if ($opData['soapAction'] == $soapAction) { - return $opData; - } - } - } - } - } - - /** - * returns an array of information about a given type - * returns false if no type exists by the given name - * - * typeDef = array( - * 'elements' => array(), // refs to elements array - * 'restrictionBase' => '', - * 'phpType' => '', - * 'order' => '(sequence|all)', - * 'attrs' => array() // refs to attributes array - * ) - * - * @param string $type the type - * @param string $ns namespace (not prefix) of the type - * @return mixed - * @access public - * @see nusoap_xmlschema - */ - function getTypeDef($type, $ns) { - $this->debug("in getTypeDef: type=$type, ns=$ns"); - if ((! $ns) && isset($this->namespaces['tns'])) { - $ns = $this->namespaces['tns']; - $this->debug("in getTypeDef: type namespace forced to $ns"); - } - if (!isset($this->schemas[$ns])) { - foreach ($this->schemas as $ns0 => $schema0) { - if (strcasecmp($ns, $ns0) == 0) { - $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0"); - $ns = $ns0; - break; - } - } - } - if (isset($this->schemas[$ns])) { - $this->debug("in getTypeDef: have schema for namespace $ns"); - for ($i = 0; $i < count($this->schemas[$ns]); $i++) { - $xs = &$this->schemas[$ns][$i]; - $t = $xs->getTypeDef($type); - $this->appendDebug($xs->getDebug()); - $xs->clearDebug(); - if ($t) { - $this->debug("in getTypeDef: found type $type"); - if (!isset($t['phpType'])) { - // get info for type to tack onto the element - $uqType = substr($t['type'], strrpos($t['type'], ':') + 1); - $ns = substr($t['type'], 0, strrpos($t['type'], ':')); - $etype = $this->getTypeDef($uqType, $ns); - if ($etype) { - $this->debug("found type for [element] $type:"); - $this->debug($this->varDump($etype)); - if (isset($etype['phpType'])) { - $t['phpType'] = $etype['phpType']; - } - if (isset($etype['elements'])) { - $t['elements'] = $etype['elements']; - } - if (isset($etype['attrs'])) { - $t['attrs'] = $etype['attrs']; - } - } else { - $this->debug("did not find type for [element] $type"); - } - } - return $t; - } - } - $this->debug("in getTypeDef: did not find type $type"); - } else { - $this->debug("in getTypeDef: do not have schema for namespace $ns"); - } - return false; - } - - /** - * prints html description of services - * - * @access private - */ - function webDescription(){ - global $HTTP_SERVER_VARS; - - if (isset($_SERVER)) { - $PHP_SELF = $_SERVER['PHP_SELF']; - } elseif (isset($HTTP_SERVER_VARS)) { - $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF']; - } else { - $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); - } - - $b = ' - NuSOAP: '.$this->serviceName.' - - - - -
    -

    -
    '.$this->serviceName.'
    - -
    '; - return $b; - } - - /** - * serialize the parsed wsdl - * - * @param mixed $debug whether to put debug=1 in endpoint URL - * @return string serialization of WSDL - * @access public - */ - function serialize($debug = 0) - { - $xml = ''; - $xml .= "\nnamespaces as $k => $v) { - $xml .= " xmlns:$k=\"$v\""; - } - // 10.9.02 - add poulter fix for wsdl and tns declarations - if (isset($this->namespaces['wsdl'])) { - $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\""; - } - if (isset($this->namespaces['tns'])) { - $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\""; - } - $xml .= '>'; - // imports - if (sizeof($this->import) > 0) { - foreach($this->import as $ns => $list) { - foreach ($list as $ii) { - if ($ii['location'] != '') { - $xml .= ''; - } else { - $xml .= ''; - } - } - } - } - // types - if (count($this->schemas)>=1) { - $xml .= "\n\n"; - foreach ($this->schemas as $ns => $list) { - foreach ($list as $xs) { - $xml .= $xs->serializeSchema(); - } - } - $xml .= ''; - } - // messages - if (count($this->messages) >= 1) { - foreach($this->messages as $msgName => $msgParts) { - $xml .= "\n'; - if(is_array($msgParts)){ - foreach($msgParts as $partName => $partType) { - // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'
    '; - if (strpos($partType, ':')) { - $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType)); - } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) { - // print 'checking typemap: '.$this->XMLSchemaVersion.'
    '; - $typePrefix = 'xsd'; - } else { - foreach($this->typemap as $ns => $types) { - if (isset($types[$partType])) { - $typePrefix = $this->getPrefixFromNamespace($ns); - } - } - if (!isset($typePrefix)) { - die("$partType has no namespace!"); - } - } - $ns = $this->getNamespaceFromPrefix($typePrefix); - $localPart = $this->getLocalPart($partType); - $typeDef = $this->getTypeDef($localPart, $ns); - if ($typeDef['typeClass'] == 'element') { - $elementortype = 'element'; - if (substr($localPart, -1) == '^') { - $localPart = substr($localPart, 0, -1); - } - } else { - $elementortype = 'type'; - } - $xml .= "\n" . ' '; - } - } - $xml .= '
    '; - } - } - // bindings & porttypes - if (count($this->bindings) >= 1) { - $binding_xml = ''; - $portType_xml = ''; - foreach($this->bindings as $bindingName => $attrs) { - $binding_xml .= "\n'; - $binding_xml .= "\n" . ' '; - $portType_xml .= "\n'; - foreach($attrs['operations'] as $opName => $opParts) { - $binding_xml .= "\n" . ' '; - $binding_xml .= "\n" . ' '; - if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') { - $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"'; - } else { - $enc_style = ''; - } - $binding_xml .= "\n" . ' '; - if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') { - $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"'; - } else { - $enc_style = ''; - } - $binding_xml .= "\n" . ' '; - $binding_xml .= "\n" . ' '; - $portType_xml .= "\n" . ' ' . htmlspecialchars($opParts['documentation']) . ''; - } - $portType_xml .= "\n" . ' '; - $portType_xml .= "\n" . ' '; - $portType_xml .= "\n" . ' '; - } - $portType_xml .= "\n" . ''; - $binding_xml .= "\n" . ''; - } - $xml .= $portType_xml . $binding_xml; - } - // services - $xml .= "\nserviceName . '">'; - if (count($this->ports) >= 1) { - foreach($this->ports as $pName => $attrs) { - $xml .= "\n" . ' '; - $xml .= "\n" . ' '; - $xml .= "\n" . ' '; - } - } - $xml .= "\n" . ''; - return $xml . "\n"; - } - - /** - * determine whether a set of parameters are unwrapped - * when they are expect to be wrapped, Microsoft-style. - * - * @param string $type the type (element name) of the wrapper - * @param array $parameters the parameter values for the SOAP call - * @return boolean whether they parameters are unwrapped (and should be wrapped) - * @access private - */ - function parametersMatchWrapped($type, &$parameters) { - $this->debug("in parametersMatchWrapped type=$type, parameters="); - $this->appendDebug($this->varDump($parameters)); - - // split type into namespace:unqualified-type - if (strpos($type, ':')) { - $uqType = substr($type, strrpos($type, ':') + 1); - $ns = substr($type, 0, strrpos($type, ':')); - $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns"); - if ($this->getNamespaceFromPrefix($ns)) { - $ns = $this->getNamespaceFromPrefix($ns); - $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns"); - } - } else { - // TODO: should the type be compared to types in XSD, and the namespace - // set to XSD if the type matches? - $this->debug("in parametersMatchWrapped: No namespace for type $type"); - $ns = ''; - $uqType = $type; - } - - // get the type information - if (!$typeDef = $this->getTypeDef($uqType, $ns)) { - $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type."); - return false; - } - $this->debug("in parametersMatchWrapped: found typeDef="); - $this->appendDebug($this->varDump($typeDef)); - if (substr($uqType, -1) == '^') { - $uqType = substr($uqType, 0, -1); - } - $phpType = $typeDef['phpType']; - $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''); - $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType"); - - // we expect a complexType or element of complexType - if ($phpType != 'struct') { - $this->debug("in parametersMatchWrapped: not a struct"); - return false; - } - - // see whether the parameter names match the elements - if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { - $elements = 0; - $matches = 0; - foreach ($typeDef['elements'] as $name => $attrs) { - if (isset($parameters[$name])) { - $this->debug("in parametersMatchWrapped: have parameter named $name"); - $matches++; - } else { - $this->debug("in parametersMatchWrapped: do not have parameter named $name"); - } - $elements++; - } - - $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names"); - if ($matches == 0) { - return false; - } - return true; - } - - // since there are no elements for the type, if the user passed no - // parameters, the parameters match wrapped. - $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType"); - return count($parameters) == 0; - } - - /** - * serialize PHP values according to a WSDL message definition - * contrary to the method name, this is not limited to RPC - * - * TODO - * - multi-ref serialization - * - validate PHP values against type definitions, return errors if invalid - * - * @param string $operation operation name - * @param string $direction (input|output) - * @param mixed $parameters parameter value(s) - * @param string $bindingType (soap|soap12) - * @return mixed parameters serialized as XML or false on error (e.g. operation not found) - * @access public - */ - function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') { - $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType"); - $this->appendDebug('parameters=' . $this->varDump($parameters)); - - if ($direction != 'input' && $direction != 'output') { - $this->debug('The value of the \$direction argument needs to be either "input" or "output"'); - $this->setError('The value of the \$direction argument needs to be either "input" or "output"'); - return false; - } - if (!$opData = $this->getOperationData($operation, $bindingType)) { - $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType); - $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType); - return false; - } - $this->debug('in serializeRPCParameters: opData:'); - $this->appendDebug($this->varDump($opData)); - - // Get encoding style for output and set to current - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) { - $encodingStyle = $opData['output']['encodingStyle']; - $enc_style = $encodingStyle; - } - - // set input params - $xml = ''; - if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) { - $parts = &$opData[$direction]['parts']; - $part_count = sizeof($parts); - $style = $opData['style']; - $use = $opData[$direction]['use']; - $this->debug("have $part_count part(s) to serialize using $style/$use"); - if (is_array($parameters)) { - $parametersArrayType = $this->isArraySimpleOrStruct($parameters); - $parameter_count = count($parameters); - $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize"); - // check for Microsoft-style wrapped parameters - if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) { - $this->debug('check whether the caller has wrapped the parameters'); - if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) { - // TODO: consider checking here for double-wrapping, when - // service function wraps, then NuSOAP wraps again - $this->debug("change simple array to associative with 'parameters' element"); - $parameters['parameters'] = $parameters[0]; - unset($parameters[0]); - } - if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) { - $this->debug('check whether caller\'s parameters match the wrapped ones'); - if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) { - $this->debug('wrap the parameters for the caller'); - $parameters = array('parameters' => $parameters); - $parameter_count = 1; - } - } - } - foreach ($parts as $name => $type) { - $this->debug("serializing part $name of type $type"); - // Track encoding style - if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) { - $encodingStyle = $opData[$direction]['encodingStyle']; - $enc_style = $encodingStyle; - } else { - $enc_style = false; - } - // NOTE: add error handling here - // if serializeType returns false, then catch global error and fault - if ($parametersArrayType == 'arraySimple') { - $p = array_shift($parameters); - $this->debug('calling serializeType w/indexed param'); - $xml .= $this->serializeType($name, $type, $p, $use, $enc_style); - } elseif (isset($parameters[$name])) { - $this->debug('calling serializeType w/named param'); - $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style); - } else { - // TODO: only send nillable - $this->debug('calling serializeType w/null param'); - $xml .= $this->serializeType($name, $type, null, $use, $enc_style); - } - } - } else { - $this->debug('no parameters passed.'); - } - } - $this->debug("serializeRPCParameters returning: $xml"); - return $xml; - } - - /** - * serialize a PHP value according to a WSDL message definition - * - * TODO - * - multi-ref serialization - * - validate PHP values against type definitions, return errors if invalid - * - * @param string $operation operation name - * @param string $direction (input|output) - * @param mixed $parameters parameter value(s) - * @return mixed parameters serialized as XML or false on error (e.g. operation not found) - * @access public - * @deprecated - */ - function serializeParameters($operation, $direction, $parameters) - { - $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion"); - $this->appendDebug('parameters=' . $this->varDump($parameters)); - - if ($direction != 'input' && $direction != 'output') { - $this->debug('The value of the \$direction argument needs to be either "input" or "output"'); - $this->setError('The value of the \$direction argument needs to be either "input" or "output"'); - return false; - } - if (!$opData = $this->getOperationData($operation)) { - $this->debug('Unable to retrieve WSDL data for operation: ' . $operation); - $this->setError('Unable to retrieve WSDL data for operation: ' . $operation); - return false; - } - $this->debug('opData:'); - $this->appendDebug($this->varDump($opData)); - - // Get encoding style for output and set to current - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) { - $encodingStyle = $opData['output']['encodingStyle']; - $enc_style = $encodingStyle; - } - - // set input params - $xml = ''; - if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) { - - $use = $opData[$direction]['use']; - $this->debug("use=$use"); - $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)'); - if (is_array($parameters)) { - $parametersArrayType = $this->isArraySimpleOrStruct($parameters); - $this->debug('have ' . $parametersArrayType . ' parameters'); - foreach($opData[$direction]['parts'] as $name => $type) { - $this->debug('serializing part "'.$name.'" of type "'.$type.'"'); - // Track encoding style - if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) { - $encodingStyle = $opData[$direction]['encodingStyle']; - $enc_style = $encodingStyle; - } else { - $enc_style = false; - } - // NOTE: add error handling here - // if serializeType returns false, then catch global error and fault - if ($parametersArrayType == 'arraySimple') { - $p = array_shift($parameters); - $this->debug('calling serializeType w/indexed param'); - $xml .= $this->serializeType($name, $type, $p, $use, $enc_style); - } elseif (isset($parameters[$name])) { - $this->debug('calling serializeType w/named param'); - $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style); - } else { - // TODO: only send nillable - $this->debug('calling serializeType w/null param'); - $xml .= $this->serializeType($name, $type, null, $use, $enc_style); - } - } - } else { - $this->debug('no parameters passed.'); - } - } - $this->debug("serializeParameters returning: $xml"); - return $xml; - } - - /** - * serializes a PHP value according a given type definition - * - * @param string $name name of value (part or element) - * @param string $type XML schema type of value (type or element) - * @param mixed $value a native PHP value (parameter value) - * @param string $use use for part (encoded|literal) - * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style) - * @param boolean $unqualified a kludge for what should be XML namespace form handling - * @return string value serialized as an XML string - * @access private - */ - function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false) - { - $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified")); - $this->appendDebug("value=" . $this->varDump($value)); - if($use == 'encoded' && $encodingStyle) { - $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"'; - } - - // if a soapval has been supplied, let its type override the WSDL - if (is_object($value) && get_class($value) == 'soapval') { - if ($value->type_ns) { - $type = $value->type_ns . ':' . $value->type; - $forceType = true; - $this->debug("in serializeType: soapval overrides type to $type"); - } elseif ($value->type) { - $type = $value->type; - $forceType = true; - $this->debug("in serializeType: soapval overrides type to $type"); - } else { - $forceType = false; - $this->debug("in serializeType: soapval does not override type"); - } - $attrs = $value->attributes; - $value = $value->value; - $this->debug("in serializeType: soapval overrides value to $value"); - if ($attrs) { - if (!is_array($value)) { - $value['!'] = $value; - } - foreach ($attrs as $n => $v) { - $value['!' . $n] = $v; - } - $this->debug("in serializeType: soapval provides attributes"); - } - } else { - $forceType = false; - } - - $xml = ''; - if (strpos($type, ':')) { - $uqType = substr($type, strrpos($type, ':') + 1); - $ns = substr($type, 0, strrpos($type, ':')); - $this->debug("in serializeType: got a prefixed type: $uqType, $ns"); - if ($this->getNamespaceFromPrefix($ns)) { - $ns = $this->getNamespaceFromPrefix($ns); - $this->debug("in serializeType: expanded prefixed type: $uqType, $ns"); - } - - if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){ - $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type'); - if ($unqualified && $use == 'literal') { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - if (is_null($value)) { - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$name$elementNS/>"; - } else { - // TODO: depends on nillable, which should be checked before calling this method - $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - if ($uqType == 'Array') { - // JBoss/Axis does this sometimes - return $this->serialize_val($value, $name, false, false, false, false, $use); - } - if ($uqType == 'boolean') { - if ((is_string($value) && $value == 'false') || (! $value)) { - $value = 'false'; - } else { - $value = 'true'; - } - } - if ($uqType == 'string' && gettype($value) == 'string') { - $value = $this->expandEntities($value); - } - if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') { - $value = sprintf("%.0lf", $value); - } - // it's a scalar - // TODO: what about null/nil values? - // check type isn't a custom type extending xmlschema namespace - if (!$this->getTypeDef($uqType, $ns)) { - if ($use == 'literal') { - if ($forceType) { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value"; - } else { - $xml = "<$name$elementNS>$value"; - } - } else { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)'); - } else if ($ns == 'http://xml.apache.org/xml-soap') { - $this->debug('in serializeType: appears to be Apache SOAP type'); - if ($uqType == 'Map') { - $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); - if (! $tt_prefix) { - $this->debug('in serializeType: Add namespace for Apache SOAP type'); - $tt_prefix = 'ns' . rand(1000, 9999); - $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap'; - // force this to be added to usedNamespaces - $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); - } - $contents = ''; - foreach($value as $k => $v) { - $this->debug("serializing map element: key $k, value $v"); - $contents .= ''; - $contents .= $this->serialize_val($k,'key',false,false,false,false,$use); - $contents .= $this->serialize_val($v,'value',false,false,false,false,$use); - $contents .= ''; - } - if ($use == 'literal') { - if ($forceType) { - $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents"; - } else { - $xml = "<$name>$contents"; - } - } else { - $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - $this->debug('in serializeType: Apache SOAP type, but only support Map'); - } - } else { - // TODO: should the type be compared to types in XSD, and the namespace - // set to XSD if the type matches? - $this->debug("in serializeType: No namespace for type $type"); - $ns = ''; - $uqType = $type; - } - if(!$typeDef = $this->getTypeDef($uqType, $ns)){ - $this->setError("$type ($uqType) is not a supported type."); - $this->debug("in serializeType: $type ($uqType) is not a supported type."); - return false; - } else { - $this->debug("in serializeType: found typeDef"); - $this->appendDebug('typeDef=' . $this->varDump($typeDef)); - if (substr($uqType, -1) == '^') { - $uqType = substr($uqType, 0, -1); - } - } - if (!isset($typeDef['phpType'])) { - $this->setError("$type ($uqType) has no phpType."); - $this->debug("in serializeType: $type ($uqType) has no phpType."); - return false; - } - $phpType = $typeDef['phpType']; - $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') ); - // if php type == struct, map value to the element names - if ($phpType == 'struct') { - if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') { - $elementName = $uqType; - if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { - $elementNS = " xmlns=\"$ns\""; - } else { - $elementNS = " xmlns=\"\""; - } - } else { - $elementName = $name; - if ($unqualified) { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - } - if (is_null($value)) { - if ($use == 'literal') { - // TODO: depends on minOccurs and nillable - $xml = "<$elementName$elementNS/>"; - } else { - $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - if (is_object($value)) { - $value = get_object_vars($value); - } - if (is_array($value)) { - $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType); - if ($use == 'literal') { - if ($forceType) { - $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">"; - } else { - $xml = "<$elementName$elementNS$elementAttrs>"; - } - } else { - $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>"; - } - - if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') { - if (isset($value['!'])) { - $xml .= $value['!']; - $this->debug("in serializeType: serialized simpleContent for type $type"); - } else { - $this->debug("in serializeType: no simpleContent to serialize for type $type"); - } - } else { - // complexContent - $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle); - } - $xml .= ""; - } else { - $this->debug("in serializeType: phpType is struct, but value is not an array"); - $this->setError("phpType is struct, but value is not an array: see debug output for details"); - $xml = ''; - } - } elseif ($phpType == 'array') { - if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { - $elementNS = " xmlns=\"$ns\""; - } else { - if ($unqualified) { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - } - if (is_null($value)) { - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$name$elementNS/>"; - } else { - $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . - $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . - ":Array\" " . - $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . - ':arrayType="' . - $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) . - ':' . - $this->getLocalPart($typeDef['arrayType'])."[0]\"/>"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - if (isset($typeDef['multidimensional'])) { - $nv = array(); - foreach($value as $v) { - $cols = ',' . sizeof($v); - $nv = array_merge($nv, $v); - } - $value = $nv; - } else { - $cols = ''; - } - if (is_array($value) && sizeof($value) >= 1) { - $rows = sizeof($value); - $contents = ''; - foreach($value as $k => $v) { - $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]"); - //if (strpos($typeDef['arrayType'], ':') ) { - if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) { - $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use); - } else { - $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use); - } - } - } else { - $rows = 0; - $contents = null; - } - // TODO: for now, an empty value will be serialized as a zero element - // array. Revisit this when coding the handling of null/nil values. - if ($use == 'literal') { - $xml = "<$name$elementNS>" - .$contents - .""; - } else { - $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '. - $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') - .':arrayType="' - .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) - .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">" - .$contents - .""; - } - } elseif ($phpType == 'scalar') { - if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { - $elementNS = " xmlns=\"$ns\""; - } else { - if ($unqualified) { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - } - if ($use == 'literal') { - if ($forceType) { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value"; - } else { - $xml = "<$name$elementNS>$value"; - } - } else { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value"; - } - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - - /** - * serializes the attributes for a complexType - * - * @param array $typeDef our internal representation of an XML schema type (or element) - * @param mixed $value a native PHP value (parameter value) - * @param string $ns the namespace of the type - * @param string $uqType the local part of the type - * @return string value serialized as an XML string - * @access private - */ - function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) { - $this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType"); - $xml = ''; - if (isset($typeDef['extensionBase'])) { - $nsx = $this->getPrefix($typeDef['extensionBase']); - $uqTypex = $this->getLocalPart($typeDef['extensionBase']); - if ($this->getNamespaceFromPrefix($nsx)) { - $nsx = $this->getNamespaceFromPrefix($nsx); - } - if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) { - $this->debug("serialize attributes for extension base $nsx:$uqTypex"); - $xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex); - } else { - $this->debug("extension base $nsx:$uqTypex is not a supported type"); - } - } - if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) { - $this->debug("serialize attributes for XML Schema type $ns:$uqType"); - if (is_array($value)) { - $xvalue = $value; - } elseif (is_object($value)) { - $xvalue = get_object_vars($value); - } else { - $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); - $xvalue = array(); - } - foreach ($typeDef['attrs'] as $aName => $attrs) { - if (isset($xvalue['!' . $aName])) { - $xname = '!' . $aName; - $this->debug("value provided for attribute $aName with key $xname"); - } elseif (isset($xvalue[$aName])) { - $xname = $aName; - $this->debug("value provided for attribute $aName with key $xname"); - } elseif (isset($attrs['default'])) { - $xname = '!' . $aName; - $xvalue[$xname] = $attrs['default']; - $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName); - } else { - $xname = ''; - $this->debug("no value provided for attribute $aName"); - } - if ($xname) { - $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\""; - } - } - } else { - $this->debug("no attributes to serialize for XML Schema type $ns:$uqType"); - } - return $xml; - } - - /** - * serializes the elements for a complexType - * - * @param array $typeDef our internal representation of an XML schema type (or element) - * @param mixed $value a native PHP value (parameter value) - * @param string $ns the namespace of the type - * @param string $uqType the local part of the type - * @param string $use use for part (encoded|literal) - * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style) - * @return string value serialized as an XML string - * @access private - */ - function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) { - $this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType"); - $xml = ''; - if (isset($typeDef['extensionBase'])) { - $nsx = $this->getPrefix($typeDef['extensionBase']); - $uqTypex = $this->getLocalPart($typeDef['extensionBase']); - if ($this->getNamespaceFromPrefix($nsx)) { - $nsx = $this->getNamespaceFromPrefix($nsx); - } - if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) { - $this->debug("serialize elements for extension base $nsx:$uqTypex"); - $xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle); - } else { - $this->debug("extension base $nsx:$uqTypex is not a supported type"); - } - } - if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { - $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType"); - if (is_array($value)) { - $xvalue = $value; - } elseif (is_object($value)) { - $xvalue = get_object_vars($value); - } else { - $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); - $xvalue = array(); - } - // toggle whether all elements are present - ideally should validate against schema - if (count($typeDef['elements']) != count($xvalue)){ - $optionals = true; - } - foreach ($typeDef['elements'] as $eName => $attrs) { - if (!isset($xvalue[$eName])) { - if (isset($attrs['default'])) { - $xvalue[$eName] = $attrs['default']; - $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName); - } - } - // if user took advantage of a minOccurs=0, then only serialize named parameters - if (isset($optionals) - && (!isset($xvalue[$eName])) - && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true') - ){ - if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') { - $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']); - } - // do nothing - $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing"); - } else { - // get value - if (isset($xvalue[$eName])) { - $v = $xvalue[$eName]; - } else { - $v = null; - } - if (isset($attrs['form'])) { - $unqualified = ($attrs['form'] == 'unqualified'); - } else { - $unqualified = false; - } - if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') { - $vv = $v; - foreach ($vv as $k => $v) { - if (isset($attrs['type']) || isset($attrs['ref'])) { - // serialize schema-defined type - $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); - } else { - // serialize generic type (can this ever really happen?) - $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use"); - $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use); - } - } - } else { - if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') { - // do nothing - } elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') { - // TODO: serialize a nil correctly, but for now serialize schema-defined type - $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); - } elseif (isset($attrs['type']) || isset($attrs['ref'])) { - // serialize schema-defined type - $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); - } else { - // serialize generic type (can this ever really happen?) - $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use"); - $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use); - } - } - } - } - } else { - $this->debug("no elements to serialize for XML Schema type $ns:$uqType"); - } - return $xml; - } - - /** - * adds an XML Schema complex type to the WSDL types - * - * @param string $name - * @param string $typeClass (complexType|simpleType|attribute) - * @param string $phpType currently supported are array and struct (php assoc array) - * @param string $compositor (all|sequence|choice) - * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param array $elements e.g. array ( name => array(name=>'',type=>'') ) - * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]')) - * @param string $arrayType as namespace:name (xsd:string) - * @see nusoap_xmlschema - * @access public - */ - function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') { - if (count($elements) > 0) { - $eElements = array(); - foreach($elements as $n => $e){ - // expand each element - $ee = array(); - foreach ($e as $k => $v) { - $k = strpos($k,':') ? $this->expandQname($k) : $k; - $v = strpos($v,':') ? $this->expandQname($v) : $v; - $ee[$k] = $v; - } - $eElements[$n] = $ee; - } - $elements = $eElements; - } - - if (count($attrs) > 0) { - foreach($attrs as $n => $a){ - // expand each attribute - foreach ($a as $k => $v) { - $k = strpos($k,':') ? $this->expandQname($k) : $k; - $v = strpos($v,':') ? $this->expandQname($v) : $v; - $aa[$k] = $v; - } - $eAttrs[$n] = $aa; - } - $attrs = $eAttrs; - } - - $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase; - $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType; - - $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; - $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType); - } - - /** - * adds an XML Schema simple type to the WSDL types - * - * @param string $name - * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param string $typeClass (should always be simpleType) - * @param string $phpType (should always be scalar) - * @param array $enumeration array of values - * @see nusoap_xmlschema - * @access public - */ - function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) { - $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase; - - $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; - $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration); - } - - /** - * adds an element to the WSDL types - * - * @param array $attrs attributes that must include name and type - * @see nusoap_xmlschema - * @access public - */ - function addElement($attrs) { - $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; - $this->schemas[$typens][0]->addElement($attrs); - } - - /** - * register an operation with the server - * - * @param string $name operation (method) name - * @param array $in assoc array of input values: key = param name, value = param type - * @param array $out assoc array of output values: key = param name, value = param type - * @param string $namespace optional The namespace for the operation - * @param string $soapaction optional The soapaction for the operation - * @param string $style (rpc|document) optional The style for the operation Note: when 'document' is specified, parameter and return wrappers are created for you automatically - * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now) - * @param string $documentation optional The description to include in the WSDL - * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) - * @access public - */ - function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){ - if ($use == 'encoded' && $encodingStyle == '') { - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - } - - if ($style == 'document') { - $elements = array(); - foreach ($in as $n => $t) { - $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified'); - } - $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements); - $this->addElement(array('name' => $name, 'type' => $name . 'RequestType')); - $in = array('parameters' => 'tns:' . $name . '^'); - - $elements = array(); - foreach ($out as $n => $t) { - $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified'); - } - $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements); - $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified')); - $out = array('parameters' => 'tns:' . $name . 'Response' . '^'); - } - - // get binding - $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] = - array( - 'name' => $name, - 'binding' => $this->serviceName . 'Binding', - 'endpoint' => $this->endpoint, - 'soapAction' => $soapaction, - 'style' => $style, - 'input' => array( - 'use' => $use, - 'namespace' => $namespace, - 'encodingStyle' => $encodingStyle, - 'message' => $name . 'Request', - 'parts' => $in), - 'output' => array( - 'use' => $use, - 'namespace' => $namespace, - 'encodingStyle' => $encodingStyle, - 'message' => $name . 'Response', - 'parts' => $out), - 'namespace' => $namespace, - 'transport' => 'http://schemas.xmlsoap.org/soap/http', - 'documentation' => $documentation); - // add portTypes - // add messages - if($in) - { - foreach($in as $pName => $pType) - { - if(strpos($pType,':')) { - $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType); - } - $this->messages[$name.'Request'][$pName] = $pType; - } - } else { - $this->messages[$name.'Request']= '0'; - } - if($out) - { - foreach($out as $pName => $pType) - { - if(strpos($pType,':')) { - $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType); - } - $this->messages[$name.'Response'][$pName] = $pType; - } - } else { - $this->messages[$name.'Response']= '0'; - } - return true; - } -} - -?> diff --git a/lib/nusoap/class.wsdlcache.php b/lib/nusoap/class.wsdlcache.php deleted file mode 100644 index 9824bb31b..000000000 --- a/lib/nusoap/class.wsdlcache.php +++ /dev/null @@ -1,209 +0,0 @@ - -* @author Ingo Fischer -* @version $Id: class.wsdlcache.php,v 1.7 2007/04/17 16:34:03 snichol Exp $ -* @access public -*/ -class nusoap_wsdlcache { - /** - * @var resource - * @access private - */ - var $fplock; - /** - * @var integer - * @access private - */ - var $cache_lifetime; - /** - * @var string - * @access private - */ - var $cache_dir; - /** - * @var string - * @access public - */ - var $debug_str = ''; - - /** - * constructor - * - * @param string $cache_dir directory for cache-files - * @param integer $cache_lifetime lifetime for caching-files in seconds or 0 for unlimited - * @access public - */ - function nusoap_wsdlcache($cache_dir='.', $cache_lifetime=0) { - $this->fplock = array(); - $this->cache_dir = $cache_dir != '' ? $cache_dir : '.'; - $this->cache_lifetime = $cache_lifetime; - } - - /** - * creates the filename used to cache a wsdl instance - * - * @param string $wsdl The URL of the wsdl instance - * @return string The filename used to cache the instance - * @access private - */ - function createFilename($wsdl) { - return $this->cache_dir.'/wsdlcache-' . md5($wsdl); - } - - /** - * adds debug data to the class level debug string - * - * @param string $string debug data - * @access private - */ - function debug($string){ - $this->debug_str .= get_class($this).": $string\n"; - } - - /** - * gets a wsdl instance from the cache - * - * @param string $wsdl The URL of the wsdl instance - * @return object wsdl The cached wsdl instance, null if the instance is not in the cache - * @access public - */ - function get($wsdl) { - $filename = $this->createFilename($wsdl); - if ($this->obtainMutex($filename, "r")) { - // check for expired WSDL that must be removed from the cache - if ($this->cache_lifetime > 0) { - if (file_exists($filename) && (time() - filemtime($filename) > $this->cache_lifetime)) { - unlink($filename); - $this->debug("Expired $wsdl ($filename) from cache"); - $this->releaseMutex($filename); - return null; - } - } - // see what there is to return - if (!file_exists($filename)) { - $this->debug("$wsdl ($filename) not in cache (1)"); - $this->releaseMutex($filename); - return null; - } - $fp = @fopen($filename, "r"); - if ($fp) { - $s = implode("", @file($filename)); - fclose($fp); - $this->debug("Got $wsdl ($filename) from cache"); - } else { - $s = null; - $this->debug("$wsdl ($filename) not in cache (2)"); - } - $this->releaseMutex($filename); - return (!is_null($s)) ? unserialize($s) : null; - } else { - $this->debug("Unable to obtain mutex for $filename in get"); - } - return null; - } - - /** - * obtains the local mutex - * - * @param string $filename The Filename of the Cache to lock - * @param string $mode The open-mode ("r" or "w") or the file - affects lock-mode - * @return boolean Lock successfully obtained ?! - * @access private - */ - function obtainMutex($filename, $mode) { - if (isset($this->fplock[md5($filename)])) { - $this->debug("Lock for $filename already exists"); - return false; - } - $this->fplock[md5($filename)] = fopen($filename.".lock", "w"); - if ($mode == "r") { - return flock($this->fplock[md5($filename)], LOCK_SH); - } else { - return flock($this->fplock[md5($filename)], LOCK_EX); - } - } - - /** - * adds a wsdl instance to the cache - * - * @param object wsdl $wsdl_instance The wsdl instance to add - * @return boolean WSDL successfully cached - * @access public - */ - function put($wsdl_instance) { - $filename = $this->createFilename($wsdl_instance->wsdl); - $s = serialize($wsdl_instance); - if ($this->obtainMutex($filename, "w")) { - $fp = fopen($filename, "w"); - if (! $fp) { - $this->debug("Cannot write $wsdl_instance->wsdl ($filename) in cache"); - $this->releaseMutex($filename); - return false; - } - fputs($fp, $s); - fclose($fp); - $this->debug("Put $wsdl_instance->wsdl ($filename) in cache"); - $this->releaseMutex($filename); - return true; - } else { - $this->debug("Unable to obtain mutex for $filename in put"); - } - return false; - } - - /** - * releases the local mutex - * - * @param string $filename The Filename of the Cache to lock - * @return boolean Lock successfully released - * @access private - */ - function releaseMutex($filename) { - $ret = flock($this->fplock[md5($filename)], LOCK_UN); - fclose($this->fplock[md5($filename)]); - unset($this->fplock[md5($filename)]); - if (! $ret) { - $this->debug("Not able to release lock for $filename"); - } - return $ret; - } - - /** - * removes a wsdl instance from the cache - * - * @param string $wsdl The URL of the wsdl instance - * @return boolean Whether there was an instance to remove - * @access public - */ - function remove($wsdl) { - $filename = $this->createFilename($wsdl); - if (!file_exists($filename)) { - $this->debug("$wsdl ($filename) not in cache to be removed"); - return false; - } - // ignore errors obtaining mutex - $this->obtainMutex($filename, "w"); - $ret = unlink($filename); - $this->debug("Removed ($ret) $wsdl ($filename) from cache"); - $this->releaseMutex($filename); - return $ret; - } -} - -/** - * For backward compatibility - */ -class wsdlcache extends nusoap_wsdlcache { -} -?> diff --git a/lib/nusoap/class.xmlschema.php b/lib/nusoap/class.xmlschema.php deleted file mode 100644 index 02866bf7e..000000000 --- a/lib/nusoap/class.xmlschema.php +++ /dev/null @@ -1,973 +0,0 @@ - -* @author Scott Nichol -* @version $Id: class.xmlschema.php,v 1.53 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_xmlschema extends nusoap_base { - - // files - var $schema = ''; - var $xml = ''; - // namespaces - var $enclosingNamespaces; - // schema info - var $schemaInfo = array(); - var $schemaTargetNamespace = ''; - // types, elements, attributes defined by the schema - var $attributes = array(); - var $complexTypes = array(); - var $complexTypeStack = array(); - var $currentComplexType = null; - var $elements = array(); - var $elementStack = array(); - var $currentElement = null; - var $simpleTypes = array(); - var $simpleTypeStack = array(); - var $currentSimpleType = null; - // imports - var $imports = array(); - // parser vars - var $parser; - var $position = 0; - var $depth = 0; - var $depth_array = array(); - var $message = array(); - var $defaultNamespace = array(); - - /** - * constructor - * - * @param string $schema schema document URI - * @param string $xml xml document URI - * @param string $namespaces namespaces defined in enclosing XML - * @access public - */ - function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){ - parent::nusoap_base(); - $this->debug('nusoap_xmlschema class instantiated, inside constructor'); - // files - $this->schema = $schema; - $this->xml = $xml; - - // namespaces - $this->enclosingNamespaces = $namespaces; - $this->namespaces = array_merge($this->namespaces, $namespaces); - - // parse schema file - if($schema != ''){ - $this->debug('initial schema file: '.$schema); - $this->parseFile($schema, 'schema'); - } - - // parse xml file - if($xml != ''){ - $this->debug('initial xml file: '.$xml); - $this->parseFile($xml, 'xml'); - } - - } - - /** - * parse an XML file - * - * @param string $xml path/URL to XML file - * @param string $type (schema | xml) - * @return boolean - * @access public - */ - function parseFile($xml,$type){ - // parse xml file - if($xml != ""){ - $xmlStr = @join("",@file($xml)); - if($xmlStr == ""){ - $msg = 'Error reading XML from '.$xml; - $this->setError($msg); - $this->debug($msg); - return false; - } else { - $this->debug("parsing $xml"); - $this->parseString($xmlStr,$type); - $this->debug("done parsing $xml"); - return true; - } - } - return false; - } - - /** - * parse an XML string - * - * @param string $xml path or URL - * @param string $type (schema|xml) - * @access private - */ - function parseString($xml,$type){ - // parse xml string - if($xml != ""){ - - // Create an XML parser. - $this->parser = xml_parser_create(); - // Set the options for parsing the XML data. - xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); - - // Set the object for the parser. - xml_set_object($this->parser, $this); - - // Set the element handlers for the parser. - if($type == "schema"){ - xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement'); - xml_set_character_data_handler($this->parser,'schemaCharacterData'); - } elseif($type == "xml"){ - xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement'); - xml_set_character_data_handler($this->parser,'xmlCharacterData'); - } - - // Parse the XML file. - if(!xml_parse($this->parser,$xml,true)){ - // Display an error message. - $errstr = sprintf('XML error parsing XML schema on line %d: %s', - xml_get_current_line_number($this->parser), - xml_error_string(xml_get_error_code($this->parser)) - ); - $this->debug($errstr); - $this->debug("XML payload:\n" . $xml); - $this->setError($errstr); - } - - xml_parser_free($this->parser); - } else{ - $this->debug('no xml passed to parseString()!!'); - $this->setError('no xml passed to parseString()!!'); - } - } - - /** - * gets a type name for an unnamed type - * - * @param string Element name - * @return string A type name for an unnamed type - * @access private - */ - function CreateTypeName($ename) { - $scope = ''; - for ($i = 0; $i < count($this->complexTypeStack); $i++) { - $scope .= $this->complexTypeStack[$i] . '_'; - } - return $scope . $ename . '_ContainedType'; - } - - /** - * start-element handler - * - * @param string $parser XML parser object - * @param string $name element name - * @param string $attrs associative array of attributes - * @access private - */ - function schemaStartElement($parser, $name, $attrs) { - - // position in the total number of elements, starting from 0 - $pos = $this->position++; - $depth = $this->depth++; - // set self as current value for this depth - $this->depth_array[$depth] = $pos; - $this->message[$pos] = array('cdata' => ''); - if ($depth > 0) { - $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]]; - } else { - $this->defaultNamespace[$pos] = false; - } - - // get element prefix - if($prefix = $this->getPrefix($name)){ - // get unqualified name - $name = $this->getLocalPart($name); - } else { - $prefix = ''; - } - - // loop thru attributes, expanding, and registering namespace declarations - if(count($attrs) > 0){ - foreach($attrs as $k => $v){ - // if ns declarations, add to class level array of valid namespaces - if(preg_match('/^xmlns/',$k)){ - //$this->xdebug("$k: $v"); - //$this->xdebug('ns_prefix: '.$this->getPrefix($k)); - if($ns_prefix = substr(strrchr($k,':'),1)){ - //$this->xdebug("Add namespace[$ns_prefix] = $v"); - $this->namespaces[$ns_prefix] = $v; - } else { - $this->defaultNamespace[$pos] = $v; - if (! $this->getPrefixFromNamespace($v)) { - $this->namespaces['ns'.(count($this->namespaces)+1)] = $v; - } - } - if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){ - $this->XMLSchemaVersion = $v; - $this->namespaces['xsi'] = $v.'-instance'; - } - } - } - foreach($attrs as $k => $v){ - // expand each attribute - $k = strpos($k,':') ? $this->expandQname($k) : $k; - $v = strpos($v,':') ? $this->expandQname($v) : $v; - $eAttrs[$k] = $v; - } - $attrs = $eAttrs; - } else { - $attrs = array(); - } - // find status, register data - switch($name){ - case 'all': // (optional) compositor content for a complexType - case 'choice': - case 'group': - case 'sequence': - //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement"); - $this->complexTypes[$this->currentComplexType]['compositor'] = $name; - //if($name == 'all' || $name == 'sequence'){ - // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; - //} - break; - case 'attribute': // complexType attribute - //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']); - $this->xdebug("parsing attribute:"); - $this->appendDebug($this->varDump($attrs)); - if (!isset($attrs['form'])) { - // TODO: handle globals - $attrs['form'] = $this->schemaInfo['attributeFormDefault']; - } - if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) { - $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - if (!strpos($v, ':')) { - // no namespace in arrayType attribute value... - if ($this->defaultNamespace[$pos]) { - // ...so use the default - $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - } - } - } - if(isset($attrs['name'])){ - $this->attributes[$attrs['name']] = $attrs; - $aname = $attrs['name']; - } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){ - if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) { - $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - } else { - $aname = ''; - } - } elseif(isset($attrs['ref'])){ - $aname = $attrs['ref']; - $this->attributes[$attrs['ref']] = $attrs; - } - - if($this->currentComplexType){ // This should *always* be - $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs; - } - // arrayType attribute - if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){ - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - $prefix = $this->getPrefix($aname); - if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){ - $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - } else { - $v = ''; - } - if(strpos($v,'[,]')){ - $this->complexTypes[$this->currentComplexType]['multidimensional'] = true; - } - $v = substr($v,0,strpos($v,'[')); // clip the [] - if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){ - $v = $this->XMLSchemaVersion.':'.$v; - } - $this->complexTypes[$this->currentComplexType]['arrayType'] = $v; - } - break; - case 'complexContent': // (optional) content for a complexType - $this->xdebug("do nothing for element $name"); - break; - case 'complexType': - array_push($this->complexTypeStack, $this->currentComplexType); - if(isset($attrs['name'])){ - // TODO: what is the scope of named complexTypes that appear - // nested within other c complexTypes? - $this->xdebug('processing named complexType '.$attrs['name']); - //$this->currentElement = false; - $this->currentComplexType = $attrs['name']; - $this->complexTypes[$this->currentComplexType] = $attrs; - $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType'; - // This is for constructs like - // - // - // - // - // - if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){ - $this->xdebug('complexType is unusual array'); - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - } else { - $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; - } - } else { - $name = $this->CreateTypeName($this->currentElement); - $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name); - $this->currentComplexType = $name; - //$this->currentElement = false; - $this->complexTypes[$this->currentComplexType] = $attrs; - $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType'; - // This is for constructs like - // - // - // - // - // - if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){ - $this->xdebug('complexType is unusual array'); - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - } else { - $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; - } - } - $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false'; - break; - case 'element': - array_push($this->elementStack, $this->currentElement); - if (!isset($attrs['form'])) { - if ($this->currentComplexType) { - $attrs['form'] = $this->schemaInfo['elementFormDefault']; - } else { - // global - $attrs['form'] = 'qualified'; - } - } - if(isset($attrs['type'])){ - $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']); - if (! $this->getPrefix($attrs['type'])) { - if ($this->defaultNamespace[$pos]) { - $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type']; - $this->xdebug('used default namespace to make type ' . $attrs['type']); - } - } - // This is for constructs like - // - // - // - // - // - if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') { - $this->xdebug('arrayType for unusual array is ' . $attrs['type']); - $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type']; - } - $this->currentElement = $attrs['name']; - $ename = $attrs['name']; - } elseif(isset($attrs['ref'])){ - $this->xdebug("processing element as ref to ".$attrs['ref']); - $this->currentElement = "ref to ".$attrs['ref']; - $ename = $this->getLocalPart($attrs['ref']); - } else { - $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']); - $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type); - $this->currentElement = $attrs['name']; - $attrs['type'] = $this->schemaTargetNamespace . ':' . $type; - $ename = $attrs['name']; - } - if (isset($ename) && $this->currentComplexType) { - $this->xdebug("add element $ename to complexType $this->currentComplexType"); - $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs; - } elseif (!isset($attrs['ref'])) { - $this->xdebug("add element $ename to elements array"); - $this->elements[ $attrs['name'] ] = $attrs; - $this->elements[ $attrs['name'] ]['typeClass'] = 'element'; - } - break; - case 'enumeration': // restriction value list member - $this->xdebug('enumeration ' . $attrs['value']); - if ($this->currentSimpleType) { - $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value']; - } elseif ($this->currentComplexType) { - $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value']; - } - break; - case 'extension': // simpleContent or complexContent type extension - $this->xdebug('extension ' . $attrs['base']); - if ($this->currentComplexType) { - $ns = $this->getPrefix($attrs['base']); - if ($ns == '') { - $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base']; - } else { - $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base']; - } - } else { - $this->xdebug('no current complexType to set extensionBase'); - } - break; - case 'import': - if (isset($attrs['schemaLocation'])) { - $this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']); - $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false); - } else { - $this->xdebug('import namespace ' . $attrs['namespace']); - $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true); - if (! $this->getPrefixFromNamespace($attrs['namespace'])) { - $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace']; - } - } - break; - case 'include': - if (isset($attrs['schemaLocation'])) { - $this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']); - $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false); - } else { - $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute'); - } - break; - case 'list': // simpleType value list - $this->xdebug("do nothing for element $name"); - break; - case 'restriction': // simpleType, simpleContent or complexContent value restriction - $this->xdebug('restriction ' . $attrs['base']); - if($this->currentSimpleType){ - $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base']; - } elseif($this->currentComplexType){ - $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base']; - if(strstr($attrs['base'],':') == ':Array'){ - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - } - } - break; - case 'schema': - $this->schemaInfo = $attrs; - $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix); - if (isset($attrs['targetNamespace'])) { - $this->schemaTargetNamespace = $attrs['targetNamespace']; - } - if (!isset($attrs['elementFormDefault'])) { - $this->schemaInfo['elementFormDefault'] = 'unqualified'; - } - if (!isset($attrs['attributeFormDefault'])) { - $this->schemaInfo['attributeFormDefault'] = 'unqualified'; - } - break; - case 'simpleContent': // (optional) content for a complexType - if ($this->currentComplexType) { // This should *always* be - $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true'; - } else { - $this->xdebug("do nothing for element $name because there is no current complexType"); - } - break; - case 'simpleType': - array_push($this->simpleTypeStack, $this->currentSimpleType); - if(isset($attrs['name'])){ - $this->xdebug("processing simpleType for name " . $attrs['name']); - $this->currentSimpleType = $attrs['name']; - $this->simpleTypes[ $attrs['name'] ] = $attrs; - $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType'; - $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar'; - } else { - $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement); - $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name); - $this->currentSimpleType = $name; - //$this->currentElement = false; - $this->simpleTypes[$this->currentSimpleType] = $attrs; - $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar'; - } - break; - case 'union': // simpleType type list - $this->xdebug("do nothing for element $name"); - break; - default: - $this->xdebug("do not have any logic to process element $name"); - } - } - - /** - * end-element handler - * - * @param string $parser XML parser object - * @param string $name element name - * @access private - */ - function schemaEndElement($parser, $name) { - // bring depth down a notch - $this->depth--; - // position of current element is equal to the last value left in depth_array for my depth - if(isset($this->depth_array[$this->depth])){ - $pos = $this->depth_array[$this->depth]; - } - // get element prefix - if ($prefix = $this->getPrefix($name)){ - // get unqualified name - $name = $this->getLocalPart($name); - } else { - $prefix = ''; - } - // move on... - if($name == 'complexType'){ - $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)')); - $this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType])); - $this->currentComplexType = array_pop($this->complexTypeStack); - //$this->currentElement = false; - } - if($name == 'element'){ - $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)')); - $this->currentElement = array_pop($this->elementStack); - } - if($name == 'simpleType'){ - $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)')); - $this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType])); - $this->currentSimpleType = array_pop($this->simpleTypeStack); - } - } - - /** - * element content handler - * - * @param string $parser XML parser object - * @param string $data element content - * @access private - */ - function schemaCharacterData($parser, $data){ - $pos = $this->depth_array[$this->depth - 1]; - $this->message[$pos]['cdata'] .= $data; - } - - /** - * serialize the schema - * - * @access public - */ - function serializeSchema(){ - - $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion); - $xml = ''; - // imports - if (sizeof($this->imports) > 0) { - foreach($this->imports as $ns => $list) { - foreach ($list as $ii) { - if ($ii['location'] != '') { - $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n"; - } else { - $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n"; - } - } - } - } - // complex types - foreach($this->complexTypes as $typeName => $attrs){ - $contentStr = ''; - // serialize child elements - if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){ - foreach($attrs['elements'] as $element => $eParts){ - if(isset($eParts['ref'])){ - $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n"; - } else { - $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\""; - foreach ($eParts as $aName => $aValue) { - // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable - if ($aName != 'name' && $aName != 'type') { - $contentStr .= " $aName=\"$aValue\""; - } - } - $contentStr .= "/>\n"; - } - } - // compositor wraps elements - if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) { - $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." \n"; - } - } - // attributes - if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){ - foreach($attrs['attrs'] as $attr => $aParts){ - $contentStr .= " <$schemaPrefix:attribute"; - foreach ($aParts as $a => $v) { - if ($a == 'ref' || $a == 'type') { - $contentStr .= " $a=\"".$this->contractQName($v).'"'; - } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') { - $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl']; - $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"'; - } else { - $contentStr .= " $a=\"$v\""; - } - } - $contentStr .= "/>\n"; - } - } - // if restriction - if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){ - $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." \n"; - // complex or simple content - if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){ - $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." \n"; - } - } - // finalize complex type - if($contentStr != ''){ - $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." \n"; - } else { - $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n"; - } - $xml .= $contentStr; - } - // simple types - if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){ - foreach($this->simpleTypes as $typeName => $eParts){ - $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n"; - if (isset($eParts['enumeration'])) { - foreach ($eParts['enumeration'] as $e) { - $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n"; - } - } - $xml .= " \n "; - } - } - // elements - if(isset($this->elements) && count($this->elements) > 0){ - foreach($this->elements as $element => $eParts){ - $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n"; - } - } - // attributes - if(isset($this->attributes) && count($this->attributes) > 0){ - foreach($this->attributes as $attr => $aParts){ - $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>"; - } - } - // finish 'er up - $attr = ''; - foreach ($this->schemaInfo as $k => $v) { - if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') { - $attr .= " $k=\"$v\""; - } - } - $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n"; - foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) { - $el .= " xmlns:$nsp=\"$ns\""; - } - $xml = $el . ">\n".$xml."\n"; - return $xml; - } - - /** - * adds debug data to the clas level debug string - * - * @param string $string debug data - * @access private - */ - function xdebug($string){ - $this->debug('<' . $this->schemaTargetNamespace . '> '.$string); - } - - /** - * get the PHP type of a user defined type in the schema - * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays - * returns false if no type exists, or not w/ the given namespace - * else returns a string that is either a native php type, or 'struct' - * - * @param string $type name of defined type - * @param string $ns namespace of type - * @return mixed - * @access public - * @deprecated - */ - function getPHPType($type,$ns){ - if(isset($this->typemap[$ns][$type])){ - //print "found type '$type' and ns $ns in typemap
    "; - return $this->typemap[$ns][$type]; - } elseif(isset($this->complexTypes[$type])){ - //print "getting type '$type' and ns $ns from complexTypes array
    "; - return $this->complexTypes[$type]['phpType']; - } - return false; - } - - /** - * returns an associative array of information about a given type - * returns false if no type exists by the given name - * - * For a complexType typeDef = array( - * 'restrictionBase' => '', - * 'phpType' => '', - * 'compositor' => '(sequence|all)', - * 'elements' => array(), // refs to elements array - * 'attrs' => array() // refs to attributes array - * ... and so on (see addComplexType) - * ) - * - * For simpleType or element, the array has different keys. - * - * @param string $type - * @return mixed - * @access public - * @see addComplexType - * @see addSimpleType - * @see addElement - */ - function getTypeDef($type){ - //$this->debug("in getTypeDef for type $type"); - if (substr($type, -1) == '^') { - $is_element = 1; - $type = substr($type, 0, -1); - } else { - $is_element = 0; - } - - if((! $is_element) && isset($this->complexTypes[$type])){ - $this->xdebug("in getTypeDef, found complexType $type"); - return $this->complexTypes[$type]; - } elseif((! $is_element) && isset($this->simpleTypes[$type])){ - $this->xdebug("in getTypeDef, found simpleType $type"); - if (!isset($this->simpleTypes[$type]['phpType'])) { - // get info for type to tack onto the simple type - // TODO: can this ever really apply (i.e. what is a simpleType really?) - $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1); - $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':')); - $etype = $this->getTypeDef($uqType); - if ($etype) { - $this->xdebug("in getTypeDef, found type for simpleType $type:"); - $this->xdebug($this->varDump($etype)); - if (isset($etype['phpType'])) { - $this->simpleTypes[$type]['phpType'] = $etype['phpType']; - } - if (isset($etype['elements'])) { - $this->simpleTypes[$type]['elements'] = $etype['elements']; - } - } - } - return $this->simpleTypes[$type]; - } elseif(isset($this->elements[$type])){ - $this->xdebug("in getTypeDef, found element $type"); - if (!isset($this->elements[$type]['phpType'])) { - // get info for type to tack onto the element - $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1); - $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':')); - $etype = $this->getTypeDef($uqType); - if ($etype) { - $this->xdebug("in getTypeDef, found type for element $type:"); - $this->xdebug($this->varDump($etype)); - if (isset($etype['phpType'])) { - $this->elements[$type]['phpType'] = $etype['phpType']; - } - if (isset($etype['elements'])) { - $this->elements[$type]['elements'] = $etype['elements']; - } - if (isset($etype['extensionBase'])) { - $this->elements[$type]['extensionBase'] = $etype['extensionBase']; - } - } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') { - $this->xdebug("in getTypeDef, element $type is an XSD type"); - $this->elements[$type]['phpType'] = 'scalar'; - } - } - return $this->elements[$type]; - } elseif(isset($this->attributes[$type])){ - $this->xdebug("in getTypeDef, found attribute $type"); - return $this->attributes[$type]; - } elseif (preg_match('/_ContainedType$/', $type)) { - $this->xdebug("in getTypeDef, have an untyped element $type"); - $typeDef['typeClass'] = 'simpleType'; - $typeDef['phpType'] = 'scalar'; - $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string'; - return $typeDef; - } - $this->xdebug("in getTypeDef, did not find $type"); - return false; - } - - /** - * returns a sample serialization of a given type, or false if no type by the given name - * - * @param string $type name of type - * @return mixed - * @access public - * @deprecated - */ - function serializeTypeDef($type){ - //print "in sTD() for type $type
    "; - if($typeDef = $this->getTypeDef($type)){ - $str .= '<'.$type; - if(is_array($typeDef['attrs'])){ - foreach($typeDef['attrs'] as $attName => $data){ - $str .= " $attName=\"{type = ".$data['type']."}\""; - } - } - $str .= " xmlns=\"".$this->schema['targetNamespace']."\""; - if(count($typeDef['elements']) > 0){ - $str .= ">"; - foreach($typeDef['elements'] as $element => $eData){ - $str .= $this->serializeTypeDef($element); - } - $str .= ""; - } elseif($typeDef['typeClass'] == 'element') { - $str .= ">"; - } else { - $str .= "/>"; - } - return $str; - } - return false; - } - - /** - * returns HTML form elements that allow a user - * to enter values for creating an instance of the given type. - * - * @param string $name name for type instance - * @param string $type name of type - * @return string - * @access public - * @deprecated - */ - function typeToForm($name,$type){ - // get typedef - if($typeDef = $this->getTypeDef($type)){ - // if struct - if($typeDef['phpType'] == 'struct'){ - $buffer .= ''; - foreach($typeDef['elements'] as $child => $childDef){ - $buffer .= " - - "; - } - $buffer .= '
    $childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):
    '; - // if array - } elseif($typeDef['phpType'] == 'array'){ - $buffer .= ''; - for($i=0;$i < 3; $i++){ - $buffer .= " - - "; - } - $buffer .= '
    array item (type: $typeDef[arrayType]):
    '; - // if scalar - } else { - $buffer .= ""; - } - } else { - $buffer .= ""; - } - return $buffer; - } - - /** - * adds a complex type to the schema - * - * example: array - * - * addType( - * 'ArrayOfstring', - * 'complexType', - * 'array', - * '', - * 'SOAP-ENC:Array', - * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'), - * 'xsd:string' - * ); - * - * example: PHP associative array ( SOAP Struct ) - * - * addType( - * 'SOAPStruct', - * 'complexType', - * 'struct', - * 'all', - * array('myVar'=> array('name'=>'myVar','type'=>'string') - * ); - * - * @param name - * @param typeClass (complexType|simpleType|attribute) - * @param phpType: currently supported are array and struct (php assoc array) - * @param compositor (all|sequence|choice) - * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param elements = array ( name = array(name=>'',type=>'') ) - * @param attrs = array( - * array( - * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType", - * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]" - * ) - * ) - * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string) - * @access public - * @see getTypeDef - */ - function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){ - $this->complexTypes[$name] = array( - 'name' => $name, - 'typeClass' => $typeClass, - 'phpType' => $phpType, - 'compositor'=> $compositor, - 'restrictionBase' => $restrictionBase, - 'elements' => $elements, - 'attrs' => $attrs, - 'arrayType' => $arrayType - ); - - $this->xdebug("addComplexType $name:"); - $this->appendDebug($this->varDump($this->complexTypes[$name])); - } - - /** - * adds a simple type to the schema - * - * @param string $name - * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param string $typeClass (should always be simpleType) - * @param string $phpType (should always be scalar) - * @param array $enumeration array of values - * @access public - * @see nusoap_xmlschema - * @see getTypeDef - */ - function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) { - $this->simpleTypes[$name] = array( - 'name' => $name, - 'typeClass' => $typeClass, - 'phpType' => $phpType, - 'type' => $restrictionBase, - 'enumeration' => $enumeration - ); - - $this->xdebug("addSimpleType $name:"); - $this->appendDebug($this->varDump($this->simpleTypes[$name])); - } - - /** - * adds an element to the schema - * - * @param array $attrs attributes that must include name and type - * @see nusoap_xmlschema - * @access public - */ - function addElement($attrs) { - if (! $this->getPrefix($attrs['type'])) { - $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type']; - } - $this->elements[ $attrs['name'] ] = $attrs; - $this->elements[ $attrs['name'] ]['typeClass'] = 'element'; - - $this->xdebug("addElement " . $attrs['name']); - $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ])); - } -} - -/** - * Backward compatibility - */ -class XMLSchema extends nusoap_xmlschema { -} - - -?> \ No newline at end of file diff --git a/lib/nusoap/docs/docs/CVS/Entries b/lib/nusoap/docs/docs/CVS/Entries deleted file mode 100644 index e98cfd699..000000000 --- a/lib/nusoap/docs/docs/CVS/Entries +++ /dev/null @@ -1,11 +0,0 @@ -D/__filesource//// -D/media//// -D/nusoap//// -/blank.html/1.1/Mon Apr 26 19:16:48 2010// -/packages.html/1.1/Mon Apr 26 19:16:48 2010// -/classtrees_nusoap.html/1.2/Mon Apr 26 19:16:48 2010// -/elementindex.html/1.2/Mon Apr 26 19:16:48 2010// -/elementindex_nusoap.html/1.2/Mon Apr 26 19:16:48 2010// -/errors.html/1.2/Mon Apr 26 19:17:11 2010// -/index.html/1.2/Mon Apr 26 19:16:48 2010// -/li_nusoap.html/1.2/Mon Apr 26 19:16:48 2010// diff --git a/lib/nusoap/docs/docs/CVS/Repository b/lib/nusoap/docs/docs/CVS/Repository deleted file mode 100644 index d8f8d4692..000000000 --- a/lib/nusoap/docs/docs/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -docs diff --git a/lib/nusoap/docs/docs/CVS/Root b/lib/nusoap/docs/docs/CVS/Root deleted file mode 100644 index 38e068369..000000000 --- a/lib/nusoap/docs/docs/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -:ext:snichol@nusoap.cvs.sourceforge.net:/cvsroot/nusoap diff --git a/lib/nusoap/docs/docs/__filesource/CVS/Entries b/lib/nusoap/docs/docs/__filesource/CVS/Entries deleted file mode 100644 index 26d14b617..000000000 --- a/lib/nusoap/docs/docs/__filesource/CVS/Entries +++ /dev/null @@ -1,4 +0,0 @@ -/fsource_nusoap__class.wsdlcache.php.html/1.2/Mon Apr 26 19:25:21 2010// -/fsource_nusoap__nusoap.php.html/1.2/Mon Apr 26 19:25:21 2010// -/fsource_nusoap__nusoapmime.php.html/1.2/Mon Apr 26 19:25:21 2010// -D diff --git a/lib/nusoap/docs/docs/__filesource/CVS/Repository b/lib/nusoap/docs/docs/__filesource/CVS/Repository deleted file mode 100644 index 4c9a42891..000000000 --- a/lib/nusoap/docs/docs/__filesource/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -docs/__filesource diff --git a/lib/nusoap/docs/docs/__filesource/CVS/Root b/lib/nusoap/docs/docs/__filesource/CVS/Root deleted file mode 100644 index 38e068369..000000000 --- a/lib/nusoap/docs/docs/__filesource/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -:ext:snichol@nusoap.cvs.sourceforge.net:/cvsroot/nusoap diff --git a/lib/nusoap/docs/docs/__filesource/fsource_nusoap__class.wsdlcache.php.html b/lib/nusoap/docs/docs/__filesource/fsource_nusoap__class.wsdlcache.php.html deleted file mode 100644 index e7a0ce42c..000000000 --- a/lib/nusoap/docs/docs/__filesource/fsource_nusoap__class.wsdlcache.php.html +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - File Source for class.wsdlcache.php - - - - -

    Source for file class.wsdlcache.php

    -

    Documentation is available at class.wsdlcache.php

    -
    -
    1. <?php
    2. -
    3. /*
    4. -
    5. The NuSOAP project home is:
    6. -
    7. http://sourceforge.net/projects/nusoap/
    8. -
    9.  
    10. -
    11. The primary support for NuSOAP is the mailing list:
    12. -
    13. nusoap-general@lists.sourceforge.net
    14. -
    15. */
    16. -
    17.  
    18. -
    19. /**
    20. -
    21. * caches instances of the wsdl class
    22. -
    23. *
    24. -
    25. * @author Scott Nichol <snichol@users.sourceforge.net>
    26. -
    27. * @author Ingo Fischer <ingo@apollon.de>
    28. -
    29. * @version $Id: fsource_nusoap__class.wsdlcache.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    30. -
    31. * @access public
    32. -
    33. */
    34. -
    35. class nusoap_wsdlcache {
    36. -
    37. /**
    38. -
    39. * @var resource
    40. -
    41. * @access private
    42. -
    43. */
    44. -
    45. var $fplock;
    46. -
    47. /**
    48. -
    49. * @var integer
    50. -
    51. * @access private
    52. -
    53. */
    54. -
    55. var $cache_lifetime;
    56. -
    57. /**
    58. -
    59. * @var string
    60. -
    61. * @access private
    62. -
    63. */
    64. -
    65. var $cache_dir;
    66. -
    67. /**
    68. -
    69. * @var string
    70. -
    71. * @access public
    72. -
    73. */
    74. -
    75. var $debug_str = '';
    76. -
    77.  
    78. -
    79. /**
    80. -
    81. * constructor
    82. -
    83. *
    84. -
    85. * @param string $cache_dir directory for cache-files
    86. -
    87. * @param integer $cache_lifetime lifetime for caching-files in seconds or 0 for unlimited
    88. -
    89. * @access public
    90. -
    91. */
    92. -
    93. function nusoap_wsdlcache($cache_dir='.', $cache_lifetime=0) {
    94. -
    95. $this->fplock = array();
    96. -
    97. $this->cache_dir = $cache_dir != '' ? $cache_dir : '.';
    98. -
    99. $this->cache_lifetime = $cache_lifetime;
    100. -
    101. }
    102. -
    103.  
    104. -
    105. /**
    106. -
    107. * creates the filename used to cache a wsdl instance
    108. -
    109. *
    110. -
    111. * @param string $wsdl The URL of the wsdl instance
    112. -
    113. * @return string The filename used to cache the instance
    114. -
    115. * @access private
    116. -
    117. */
    118. -
    119. function createFilename($wsdl) {
    120. -
    121. return $this->cache_dir.'/wsdlcache-' . md5($wsdl);
    122. -
    123. }
    124. -
    125.  
    126. -
    127. /**
    128. -
    129. * adds debug data to the class level debug string
    130. -
    131. *
    132. -
    133. * @param string $string debug data
    134. -
    135. * @access private
    136. -
    137. */
    138. -
    139. function debug($string){
    140. -
    141. $this->debug_str .= get_class($this).": $string\n";
    142. -
    143. }
    144. -
    145.  
    146. -
    147. /**
    148. -
    149. * gets a wsdl instance from the cache
    150. -
    151. *
    152. -
    153. * @param string $wsdl The URL of the wsdl instance
    154. -
    155. * @return object wsdl The cached wsdl instance, null if the instance is not in the cache
    156. -
    157. * @access public
    158. -
    159. */
    160. -
    161. function get($wsdl) {
    162. -
    163. $filename = $this->createFilename($wsdl);
    164. -
    165. if ($this->obtainMutex($filename, "r")) {
    166. -
    167. // check for expired WSDL that must be removed from the cache
    168. -
    169. if ($this->cache_lifetime > 0) {
    170. -
    171. if (file_exists($filename) && (time() - filemtime($filename) > $this->cache_lifetime)) {
    172. -
    173. unlink($filename);
    174. -
    175. $this->debug("Expired $wsdl ($filename) from cache");
    176. -
    177. $this->releaseMutex($filename);
    178. -
    179. return null;
    180. -
    181. }
    182. -
    183. }
    184. -
    185. // see what there is to return
    186. -
    187. if (!file_exists($filename)) {
    188. -
    189. $this->debug("$wsdl ($filename) not in cache (1)");
    190. -
    191. $this->releaseMutex($filename);
    192. -
    193. return null;
    194. -
    195. }
    196. -
    197. $fp = @fopen($filename, "r");
    198. -
    199. if ($fp) {
    200. -
    201. $s = implode("", @file($filename));
    202. -
    203. fclose($fp);
    204. -
    205. $this->debug("Got $wsdl ($filename) from cache");
    206. -
    207. } else {
    208. -
    209. $s = null;
    210. -
    211. $this->debug("$wsdl ($filename) not in cache (2)");
    212. -
    213. }
    214. -
    215. $this->releaseMutex($filename);
    216. -
    217. return (!is_null($s)) ? unserialize($s) : null;
    218. -
    219. } else {
    220. -
    221. $this->debug("Unable to obtain mutex for $filename in get");
    222. -
    223. }
    224. -
    225. return null;
    226. -
    227. }
    228. -
    229.  
    230. -
    231. /**
    232. -
    233. * obtains the local mutex
    234. -
    235. *
    236. -
    237. * @param string $filename The Filename of the Cache to lock
    238. -
    239. * @param string $mode The open-mode ("r" or "w") or the file - affects lock-mode
    240. -
    241. * @return boolean Lock successfully obtained ?!
    242. -
    243. * @access private
    244. -
    245. */
    246. -
    247. function obtainMutex($filename, $mode) {
    248. -
    249. if (isset($this->fplock[md5($filename)])) {
    250. -
    251. $this->debug("Lock for $filename already exists");
    252. -
    253. return false;
    254. -
    255. }
    256. -
    257. $this->fplock[md5($filename)] = fopen($filename.".lock", "w");
    258. -
    259. if ($mode == "r") {
    260. -
    261. return flock($this->fplock[md5($filename)], LOCK_SH);
    262. -
    263. } else {
    264. -
    265. return flock($this->fplock[md5($filename)], LOCK_EX);
    266. -
    267. }
    268. -
    269. }
    270. -
    271.  
    272. -
    273. /**
    274. -
    275. * adds a wsdl instance to the cache
    276. -
    277. *
    278. -
    279. * @param object wsdl $wsdl_instance The wsdl instance to add
    280. -
    281. * @return boolean WSDL successfully cached
    282. -
    283. * @access public
    284. -
    285. */
    286. -
    287. function put($wsdl_instance) {
    288. -
    289. $filename = $this->createFilename($wsdl_instance->wsdl);
    290. -
    291. $s = serialize($wsdl_instance);
    292. -
    293. if ($this->obtainMutex($filename, "w")) {
    294. -
    295. $fp = fopen($filename, "w");
    296. -
    297. if (! $fp) {
    298. -
    299. $this->debug("Cannot write $wsdl_instance->wsdl ($filename) in cache");
    300. -
    301. $this->releaseMutex($filename);
    302. -
    303. return false;
    304. -
    305. }
    306. -
    307. fputs($fp, $s);
    308. -
    309. fclose($fp);
    310. -
    311. $this->debug("Put $wsdl_instance->wsdl ($filename) in cache");
    312. -
    313. $this->releaseMutex($filename);
    314. -
    315. return true;
    316. -
    317. } else {
    318. -
    319. $this->debug("Unable to obtain mutex for $filename in put");
    320. -
    321. }
    322. -
    323. return false;
    324. -
    325. }
    326. -
    327.  
    328. -
    329. /**
    330. -
    331. * releases the local mutex
    332. -
    333. *
    334. -
    335. * @param string $filename The Filename of the Cache to lock
    336. -
    337. * @return boolean Lock successfully released
    338. -
    339. * @access private
    340. -
    341. */
    342. -
    343. function releaseMutex($filename) {
    344. -
    345. $ret = flock($this->fplock[md5($filename)], LOCK_UN);
    346. -
    347. fclose($this->fplock[md5($filename)]);
    348. -
    349. unset($this->fplock[md5($filename)]);
    350. -
    351. if (! $ret) {
    352. -
    353. $this->debug("Not able to release lock for $filename");
    354. -
    355. }
    356. -
    357. return $ret;
    358. -
    359. }
    360. -
    361.  
    362. -
    363. /**
    364. -
    365. * removes a wsdl instance from the cache
    366. -
    367. *
    368. -
    369. * @param string $wsdl The URL of the wsdl instance
    370. -
    371. * @return boolean Whether there was an instance to remove
    372. -
    373. * @access public
    374. -
    375. */
    376. -
    377. function remove($wsdl) {
    378. -
    379. $filename = $this->createFilename($wsdl);
    380. -
    381. if (!file_exists($filename)) {
    382. -
    383. $this->debug("$wsdl ($filename) not in cache to be removed");
    384. -
    385. return false;
    386. -
    387. }
    388. -
    389. // ignore errors obtaining mutex
    390. -
    391. $this->obtainMutex($filename, "w");
    392. -
    393. $ret = unlink($filename);
    394. -
    395. $this->debug("Removed ($ret) $wsdl ($filename) from cache");
    396. -
    397. $this->releaseMutex($filename);
    398. -
    399. return $ret;
    400. -
    401. }
    402. -
    403. }
    404. -
    405.  
    406. -
    407. /**
    408. -
    409. * For backward compatibility
    410. -
    411. */
    412. -
    413. class wsdlcache extends nusoap_wsdlcache {
    414. -
    415. }
    416. -
    417. ?>
    418. -
    -
    -

    - Documentation generated on Mon, 26 Apr 2010 16:16:49 -0400 by phpDocumentor 1.3.0RC3 -

    - - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/__filesource/fsource_nusoap__nusoap.php.html b/lib/nusoap/docs/docs/__filesource/fsource_nusoap__nusoap.php.html deleted file mode 100644 index 977b89f27..000000000 --- a/lib/nusoap/docs/docs/__filesource/fsource_nusoap__nusoap.php.html +++ /dev/null @@ -1,8228 +0,0 @@ - - - - - - File Source for nusoap.php - - - - -

    Source for file nusoap.php

    -

    Documentation is available at nusoap.php

    -
    -
    1. <?php
    2. -
    3.  
    4. -
    5. /*
    6. -
    7. $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    8. -
    9.  
    10. -
    11. NuSOAP - Web Services Toolkit for PHP
    12. -
    13.  
    14. -
    15. Copyright (c) 2002 NuSphere Corporation
    16. -
    17.  
    18. -
    19. This library is free software; you can redistribute it and/or
    20. -
    21. modify it under the terms of the GNU Lesser General Public
    22. -
    23. License as published by the Free Software Foundation; either
    24. -
    25. version 2.1 of the License, or (at your option) any later version.
    26. -
    27.  
    28. -
    29. This library is distributed in the hope that it will be useful,
    30. -
    31. but WITHOUT ANY WARRANTY; without even the implied warranty of
    32. -
    33. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    34. -
    35. Lesser General Public License for more details.
    36. -
    37.  
    38. -
    39. You should have received a copy of the GNU Lesser General Public
    40. -
    41. License along with this library; if not, write to the Free Software
    42. -
    43. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    44. -
    45.  
    46. -
    47. The NuSOAP project home is:
    48. -
    49. http://sourceforge.net/projects/nusoap/
    50. -
    51.  
    52. -
    53. The primary support for NuSOAP is the Help forum on the project home page.
    54. -
    55.  
    56. -
    57. If you have any questions or comments, please email:
    58. -
    59.  
    60. -
    61. Dietrich Ayala
    62. -
    63. dietrich@ganx4.com
    64. -
    65. http://dietrich.ganx4.com/nusoap
    66. -
    67.  
    68. -
    69. NuSphere Corporation
    70. -
    71. http://www.nusphere.com
    72. -
    73.  
    74. -
    75. */
    76. -
    77.  
    78. -
    79. /*
    80. -
    81. * Some of the standards implmented in whole or part by NuSOAP:
    82. -
    83. *
    84. -
    85. * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
    86. -
    87. * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
    88. -
    89. * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
    90. -
    91. * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
    92. -
    93. * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
    94. -
    95. * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
    96. -
    97. * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
    98. -
    99. * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
    100. -
    101. * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
    102. -
    103. */
    104. -
    105.  
    106. -
    107. /* load classes
    108. -
    109. // necessary classes
    110. -
    111. require_once('class.soapclient.php');
    112. -
    113. require_once('class.soap_val.php');
    114. -
    115. require_once('class.soap_parser.php');
    116. -
    117. require_once('class.soap_fault.php');
    118. -
    119.  
    120. -
    121. // transport classes
    122. -
    123. require_once('class.soap_transport_http.php');
    124. -
    125.  
    126. -
    127. // optional add-on classes
    128. -
    129. require_once('class.xmlschema.php');
    130. -
    131. require_once('class.wsdl.php');
    132. -
    133.  
    134. -
    135. // server class
    136. -
    137. require_once('class.soap_server.php');*/
    138. -
    139.  
    140. -
    141. // class variable emulation
    142. -
    143. // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
    144. -
    145.  
    146. -
    147. $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 9;
    148. -
    149.  
    150. -
    151. /**
    152. -
    153. *
    154. -
    155. * nusoap_base
    156. -
    157. *
    158. -
    159. * @author Dietrich Ayala <dietrich@ganx4.com>
    160. -
    161. * @author Scott Nichol <snichol@users.sourceforge.net>
    162. -
    163. * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    164. -
    165. * @access public
    166. -
    167. */
    168. -
    169. class nusoap_base {
    170. -
    171. /**
    172. -
    173. * Identification for HTTP headers.
    174. -
    175. *
    176. -
    177. * @var string
    178. -
    179. * @access private
    180. -
    181. */
    182. -
    183. var $title = 'NuSOAP';
    184. -
    185. /**
    186. -
    187. * Version for HTTP headers.
    188. -
    189. *
    190. -
    191. * @var string
    192. -
    193. * @access private
    194. -
    195. */
    196. -
    197. var $version = '0.9.5';
    198. -
    199. /**
    200. -
    201. * CVS revision for HTTP headers.
    202. -
    203. *
    204. -
    205. * @var string
    206. -
    207. * @access private
    208. -
    209. */
    210. -
    211. var $revision = '$Revision: 1.2 $';
    212. -
    213. /**
    214. -
    215. * Current error string (manipulated by getError/setError)
    216. -
    217. *
    218. -
    219. * @var string
    220. -
    221. * @access private
    222. -
    223. */
    224. -
    225. var $error_str = '';
    226. -
    227. /**
    228. -
    229. * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
    230. -
    231. *
    232. -
    233. * @var string
    234. -
    235. * @access private
    236. -
    237. */
    238. -
    239. var $debug_str = '';
    240. -
    241. /**
    242. -
    243. * toggles automatic encoding of special characters as entities
    244. -
    245. * (should always be true, I think)
    246. -
    247. *
    248. -
    249. * @var boolean
    250. -
    251. * @access private
    252. -
    253. */
    254. -
    255. var $charencoding = true;
    256. -
    257. /**
    258. -
    259. * the debug level for this instance
    260. -
    261. *
    262. -
    263. * @var integer
    264. -
    265. * @access private
    266. -
    267. */
    268. -
    269. var $debugLevel;
    270. -
    271.  
    272. -
    273. /**
    274. -
    275. * set schema version
    276. -
    277. *
    278. -
    279. * @var string
    280. -
    281. * @access public
    282. -
    283. */
    284. -
    285. var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
    286. -
    287. -
    288. /**
    289. -
    290. * charset encoding for outgoing messages
    291. -
    292. *
    293. -
    294. * @var string
    295. -
    296. * @access public
    297. -
    298. */
    299. -
    300. var $soap_defencoding = 'ISO-8859-1';
    301. -
    302. //var $soap_defencoding = 'UTF-8';
    303. -
    304.  
    305. -
    306. -
    307.  
    308. -
    309. /**
    310. -
    311. * namespaces in an array of prefix => uri
    312. -
    313. *
    314. -
    315. * this is "seeded" by a set of constants, but it may be altered by code
    316. -
    317. *
    318. -
    319. * @var array
    320. -
    321. * @access public
    322. -
    323. */
    324. -
    325. var $namespaces = array(
    326. -
    327. 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
    328. -
    329. 'xsd' => 'http://www.w3.org/2001/XMLSchema',
    330. -
    331. 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
    332. -
    333. 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
    334. -
    335. );
    336. -
    337.  
    338. -
    339. /**
    340. -
    341. * namespaces used in the current context, e.g. during serialization
    342. -
    343. *
    344. -
    345. * @var array
    346. -
    347. * @access private
    348. -
    349. */
    350. -
    351. var $usedNamespaces = array();
    352. -
    353.  
    354. -
    355. /**
    356. -
    357. * XML Schema types in an array of uri => (array of xml type => php type)
    358. -
    359. * is this legacy yet?
    360. -
    361. * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
    362. -
    363. * @var array
    364. -
    365. * @access public
    366. -
    367. */
    368. -
    369. var $typemap = array(
    370. -
    371. 'http://www.w3.org/2001/XMLSchema' => array(
    372. -
    373. 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
    374. -
    375. 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
    376. -
    377. 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
    378. -
    379. // abstract "any" types
    380. -
    381. -
    382. 'anyType'=>'string','anySimpleType'=>'string',
    383. -
    384. // derived datatypes
    385. -
    386. -
    387. 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
    388. -
    389. 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
    390. -
    391. 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
    392. -
    393. 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
    394. -
    395. 'http://www.w3.org/2000/10/XMLSchema' => array(
    396. -
    397. 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
    398. -
    399. 'float'=>'double','dateTime'=>'string',
    400. -
    401. 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
    402. -
    403. 'http://www.w3.org/1999/XMLSchema' => array(
    404. -
    405. 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
    406. -
    407. 'float'=>'double','dateTime'=>'string',
    408. -
    409. 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
    410. -
    411. 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
    412. -
    413. 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
    414. -
    415. 'http://xml.apache.org/xml-soap' => array('Map')
    416. -
    417. );
    418. -
    419.  
    420. -
    421. /**
    422. -
    423. * XML entities to convert
    424. -
    425. *
    426. -
    427. * @var array
    428. -
    429. * @access public
    430. -
    431. * @deprecated
    432. -
    433. * @see expandEntities
    434. -
    435. */
    436. -
    437. var $xmlEntities = array('quot' => '"','amp' => '&',
    438. -
    439. 'lt' => '<','gt' => '>','apos' => "'");
    440. -
    441.  
    442. -
    443. /**
    444. -
    445. * constructor
    446. -
    447. *
    448. -
    449. * @access public
    450. -
    451. */
    452. -
    453. function nusoap_base() {
    454. -
    455. $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
    456. -
    457. }
    458. -
    459.  
    460. -
    461. /**
    462. -
    463. * gets the global debug level, which applies to future instances
    464. -
    465. *
    466. -
    467. * @return integer Debug level 0-9, where 0 turns off
    468. -
    469. * @access public
    470. -
    471. */
    472. -
    473. function getGlobalDebugLevel() {
    474. -
    475. return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
    476. -
    477. }
    478. -
    479.  
    480. -
    481. /**
    482. -
    483. * sets the global debug level, which applies to future instances
    484. -
    485. *
    486. -
    487. * @param int $level Debug level 0-9, where 0 turns off
    488. -
    489. * @access public
    490. -
    491. */
    492. -
    493. function setGlobalDebugLevel($level) {
    494. -
    495. $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
    496. -
    497. }
    498. -
    499.  
    500. -
    501. /**
    502. -
    503. * gets the debug level for this instance
    504. -
    505. *
    506. -
    507. * @return int Debug level 0-9, where 0 turns off
    508. -
    509. * @access public
    510. -
    511. */
    512. -
    513. function getDebugLevel() {
    514. -
    515. return $this->debugLevel;
    516. -
    517. }
    518. -
    519.  
    520. -
    521. /**
    522. -
    523. * sets the debug level for this instance
    524. -
    525. *
    526. -
    527. * @param int $level Debug level 0-9, where 0 turns off
    528. -
    529. * @access public
    530. -
    531. */
    532. -
    533. function setDebugLevel($level) {
    534. -
    535. $this->debugLevel = $level;
    536. -
    537. }
    538. -
    539.  
    540. -
    541. /**
    542. -
    543. * adds debug data to the instance debug string with formatting
    544. -
    545. *
    546. -
    547. * @param string $string debug data
    548. -
    549. * @access private
    550. -
    551. */
    552. -
    553. function debug($string){
    554. -
    555. if ($this->debugLevel > 0) {
    556. -
    557. $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
    558. -
    559. }
    560. -
    561. }
    562. -
    563.  
    564. -
    565. /**
    566. -
    567. * adds debug data to the instance debug string without formatting
    568. -
    569. *
    570. -
    571. * @param string $string debug data
    572. -
    573. * @access public
    574. -
    575. */
    576. -
    577. function appendDebug($string){
    578. -
    579. if ($this->debugLevel > 0) {
    580. -
    581. // it would be nice to use a memory stream here to use
    582. -
    583. // memory more efficiently
    584. -
    585. $this->debug_str .= $string;
    586. -
    587. }
    588. -
    589. }
    590. -
    591.  
    592. -
    593. /**
    594. -
    595. * clears the current debug data for this instance
    596. -
    597. *
    598. -
    599. * @access public
    600. -
    601. */
    602. -
    603. function clearDebug() {
    604. -
    605. // it would be nice to use a memory stream here to use
    606. -
    607. // memory more efficiently
    608. -
    609. $this->debug_str = '';
    610. -
    611. }
    612. -
    613.  
    614. -
    615. /**
    616. -
    617. * gets the current debug data for this instance
    618. -
    619. *
    620. -
    621. * @return debug data
    622. -
    623. * @access public
    624. -
    625. */
    626. -
    627. function &getDebug() {
    628. -
    629. // it would be nice to use a memory stream here to use
    630. -
    631. // memory more efficiently
    632. -
    633. return $this->debug_str;
    634. -
    635. }
    636. -
    637.  
    638. -
    639. /**
    640. -
    641. * gets the current debug data for this instance as an XML comment
    642. -
    643. * this may change the contents of the debug data
    644. -
    645. *
    646. -
    647. * @return debug data as an XML comment
    648. -
    649. * @access public
    650. -
    651. */
    652. -
    653. function &getDebugAsXMLComment() {
    654. -
    655. // it would be nice to use a memory stream here to use
    656. -
    657. // memory more efficiently
    658. -
    659. while (strpos($this->debug_str, '--')) {
    660. -
    661. $this->debug_str = str_replace('--', '- -', $this->debug_str);
    662. -
    663. }
    664. -
    665. $ret = "<!--\n" . $this->debug_str . "\n-->";
    666. -
    667. return $ret;
    668. -
    669. }
    670. -
    671.  
    672. -
    673. /**
    674. -
    675. * expands entities, e.g. changes '<' to '&lt;'.
    676. -
    677. *
    678. -
    679. * @param string $val The string in which to expand entities.
    680. -
    681. * @access private
    682. -
    683. */
    684. -
    685. function expandEntities($val) {
    686. -
    687. if ($this->charencoding) {
    688. -
    689. $val = str_replace('&', '&amp;', $val);
    690. -
    691. $val = str_replace("'", '&apos;', $val);
    692. -
    693. $val = str_replace('"', '&quot;', $val);
    694. -
    695. $val = str_replace('<', '&lt;', $val);
    696. -
    697. $val = str_replace('>', '&gt;', $val);
    698. -
    699. }
    700. -
    701. return $val;
    702. -
    703. }
    704. -
    705.  
    706. -
    707. /**
    708. -
    709. * returns error string if present
    710. -
    711. *
    712. -
    713. * @return mixed error string or false
    714. -
    715. * @access public
    716. -
    717. */
    718. -
    719. function getError(){
    720. -
    721. if($this->error_str != ''){
    722. -
    723. return $this->error_str;
    724. -
    725. }
    726. -
    727. return false;
    728. -
    729. }
    730. -
    731.  
    732. -
    733. /**
    734. -
    735. * sets error string
    736. -
    737. *
    738. -
    739. * @return boolean $string error string
    740. -
    741. * @access private
    742. -
    743. */
    744. -
    745. function setError($str){
    746. -
    747. $this->error_str = $str;
    748. -
    749. }
    750. -
    751.  
    752. -
    753. /**
    754. -
    755. * detect if array is a simple array or a struct (associative array)
    756. -
    757. *
    758. -
    759. * @param mixed $val The PHP array
    760. -
    761. * @return string (arraySimple|arrayStruct)
    762. -
    763. * @access private
    764. -
    765. */
    766. -
    767. function isArraySimpleOrStruct($val) {
    768. -
    769. $keyList = array_keys($val);
    770. -
    771. foreach ($keyList as $keyListValue) {
    772. -
    773. if (!is_int($keyListValue)) {
    774. -
    775. return 'arrayStruct';
    776. -
    777. }
    778. -
    779. }
    780. -
    781. return 'arraySimple';
    782. -
    783. }
    784. -
    785.  
    786. -
    787. /**
    788. -
    789. * serializes PHP values in accordance w/ section 5. Type information is
    790. -
    791. * not serialized if $use == 'literal'.
    792. -
    793. *
    794. -
    795. * @param mixed $val The value to serialize
    796. -
    797. * @param string $name The name (local part) of the XML element
    798. -
    799. * @param string $type The XML schema type (local part) for the element
    800. -
    801. * @param string $name_ns The namespace for the name of the XML element
    802. -
    803. * @param string $type_ns The namespace for the type of the element
    804. -
    805. * @param array $attributes The attributes to serialize as name=>value pairs
    806. -
    807. * @param string $use The WSDL "use" (encoded|literal)
    808. -
    809. * @param boolean $soapval Whether this is called from soapval.
    810. -
    811. * @return string The serialized element, possibly with child elements
    812. -
    813. * @access public
    814. -
    815. */
    816. -
    817. function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
    818. -
    819. $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
    820. -
    821. $this->appendDebug('value=' . $this->varDump($val));
    822. -
    823. $this->appendDebug('attributes=' . $this->varDump($attributes));
    824. -
    825. -
    826. if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
    827. -
    828. $this->debug("serialize_val: serialize soapval");
    829. -
    830. $xml = $val->serialize($use);
    831. -
    832. $this->appendDebug($val->getDebug());
    833. -
    834. $val->clearDebug();
    835. -
    836. $this->debug("serialize_val of soapval returning $xml");
    837. -
    838. return $xml;
    839. -
    840. }
    841. -
    842. // force valid name if necessary
    843. -
    844. if (is_numeric($name)) {
    845. -
    846. $name = '__numeric_' . $name;
    847. -
    848. } elseif (! $name) {
    849. -
    850. $name = 'noname';
    851. -
    852. }
    853. -
    854. // if name has ns, add ns prefix to name
    855. -
    856. $xmlns = '';
    857. -
    858. if($name_ns){
    859. -
    860. $prefix = 'nu'.rand(1000,9999);
    861. -
    862. $name = $prefix.':'.$name;
    863. -
    864. $xmlns .= " xmlns:$prefix=\"$name_ns\"";
    865. -
    866. }
    867. -
    868. // if type is prefixed, create type prefix
    869. -
    870. if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
    871. -
    872. // need to fix this. shouldn't default to xsd if no ns specified
    873. -
    874. // w/o checking against typemap
    875. -
    876. $type_prefix = 'xsd';
    877. -
    878. } elseif($type_ns){
    879. -
    880. $type_prefix = 'ns'.rand(1000,9999);
    881. -
    882. $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
    883. -
    884. }
    885. -
    886. // serialize attributes if present
    887. -
    888. $atts = '';
    889. -
    890. if($attributes){
    891. -
    892. foreach($attributes as $k => $v){
    893. -
    894. $atts .= " $k=\"".$this->expandEntities($v).'"';
    895. -
    896. }
    897. -
    898. }
    899. -
    900. // serialize null value
    901. -
    902. if (is_null($val)) {
    903. -
    904. $this->debug("serialize_val: serialize null");
    905. -
    906. if ($use == 'literal') {
    907. -
    908. // TODO: depends on minOccurs
    909. -
    910. $xml = "<$name$xmlns$atts/>";
    911. -
    912. $this->debug("serialize_val returning $xml");
    913. -
    914. return $xml;
    915. -
    916. } else {
    917. -
    918. if (isset($type) && isset($type_prefix)) {
    919. -
    920. $type_str = " xsi:type=\"$type_prefix:$type\"";
    921. -
    922. } else {
    923. -
    924. $type_str = '';
    925. -
    926. }
    927. -
    928. $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
    929. -
    930. $this->debug("serialize_val returning $xml");
    931. -
    932. return $xml;
    933. -
    934. }
    935. -
    936. }
    937. -
    938. // serialize if an xsd built-in primitive type
    939. -
    940. if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
    941. -
    942. $this->debug("serialize_val: serialize xsd built-in primitive type");
    943. -
    944. if (is_bool($val)) {
    945. -
    946. if ($type == 'boolean') {
    947. -
    948. $val = $val ? 'true' : 'false';
    949. -
    950. } elseif (! $val) {
    951. -
    952. $val = 0;
    953. -
    954. }
    955. -
    956. } else if (is_string($val)) {
    957. -
    958. $val = $this->expandEntities($val);
    959. -
    960. }
    961. -
    962. if ($use == 'literal') {
    963. -
    964. $xml = "<$name$xmlns$atts>$val</$name>";
    965. -
    966. $this->debug("serialize_val returning $xml");
    967. -
    968. return $xml;
    969. -
    970. } else {
    971. -
    972. $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
    973. -
    974. $this->debug("serialize_val returning $xml");
    975. -
    976. return $xml;
    977. -
    978. }
    979. -
    980. }
    981. -
    982. // detect type and serialize
    983. -
    984. $xml = '';
    985. -
    986. switch(true) {
    987. -
    988. case (is_bool($val) || $type == 'boolean'):
    989. -
    990. $this->debug("serialize_val: serialize boolean");
    991. -
    992. if ($type == 'boolean') {
    993. -
    994. $val = $val ? 'true' : 'false';
    995. -
    996. } elseif (! $val) {
    997. -
    998. $val = 0;
    999. -
    1000. }
    1001. -
    1002. if ($use == 'literal') {
    1003. -
    1004. $xml .= "<$name$xmlns$atts>$val</$name>";
    1005. -
    1006. } else {
    1007. -
    1008. $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
    1009. -
    1010. }
    1011. -
    1012. break;
    1013. -
    1014. case (is_int($val) || is_long($val) || $type == 'int'):
    1015. -
    1016. $this->debug("serialize_val: serialize int");
    1017. -
    1018. if ($use == 'literal') {
    1019. -
    1020. $xml .= "<$name$xmlns$atts>$val</$name>";
    1021. -
    1022. } else {
    1023. -
    1024. $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
    1025. -
    1026. }
    1027. -
    1028. break;
    1029. -
    1030. case (is_float($val)|| is_double($val) || $type == 'float'):
    1031. -
    1032. $this->debug("serialize_val: serialize float");
    1033. -
    1034. if ($use == 'literal') {
    1035. -
    1036. $xml .= "<$name$xmlns$atts>$val</$name>";
    1037. -
    1038. } else {
    1039. -
    1040. $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
    1041. -
    1042. }
    1043. -
    1044. break;
    1045. -
    1046. case (is_string($val) || $type == 'string'):
    1047. -
    1048. $this->debug("serialize_val: serialize string");
    1049. -
    1050. $val = $this->expandEntities($val);
    1051. -
    1052. if ($use == 'literal') {
    1053. -
    1054. $xml .= "<$name$xmlns$atts>$val</$name>";
    1055. -
    1056. } else {
    1057. -
    1058. $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
    1059. -
    1060. }
    1061. -
    1062. break;
    1063. -
    1064. case is_object($val):
    1065. -
    1066. $this->debug("serialize_val: serialize object");
    1067. -
    1068. if (get_class($val) == 'soapval') {
    1069. -
    1070. $this->debug("serialize_val: serialize soapval object");
    1071. -
    1072. $pXml = $val->serialize($use);
    1073. -
    1074. $this->appendDebug($val->getDebug());
    1075. -
    1076. $val->clearDebug();
    1077. -
    1078. } else {
    1079. -
    1080. if (! $name) {
    1081. -
    1082. $name = get_class($val);
    1083. -
    1084. $this->debug("In serialize_val, used class name $name as element name");
    1085. -
    1086. } else {
    1087. -
    1088. $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
    1089. -
    1090. }
    1091. -
    1092. foreach(get_object_vars($val) as $k => $v){
    1093. -
    1094. $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
    1095. -
    1096. }
    1097. -
    1098. }
    1099. -
    1100. if(isset($type) && isset($type_prefix)){
    1101. -
    1102. $type_str = " xsi:type=\"$type_prefix:$type\"";
    1103. -
    1104. } else {
    1105. -
    1106. $type_str = '';
    1107. -
    1108. }
    1109. -
    1110. if ($use == 'literal') {
    1111. -
    1112. $xml .= "<$name$xmlns$atts>$pXml</$name>";
    1113. -
    1114. } else {
    1115. -
    1116. $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
    1117. -
    1118. }
    1119. -
    1120. break;
    1121. -
    1122. break;
    1123. -
    1124. case (is_array($val) || $type):
    1125. -
    1126. // detect if struct or array
    1127. -
    1128. $valueType = $this->isArraySimpleOrStruct($val);
    1129. -
    1130. if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
    1131. -
    1132. $this->debug("serialize_val: serialize array");
    1133. -
    1134. $i = 0;
    1135. -
    1136. if(is_array($val) && count($val)> 0){
    1137. -
    1138. foreach($val as $v){
    1139. -
    1140. if(is_object($v) && get_class($v) == 'soapval'){
    1141. -
    1142. $tt_ns = $v->type_ns;
    1143. -
    1144. $tt = $v->type;
    1145. -
    1146. } elseif (is_array($v)) {
    1147. -
    1148. $tt = $this->isArraySimpleOrStruct($v);
    1149. -
    1150. } else {
    1151. -
    1152. $tt = gettype($v);
    1153. -
    1154. }
    1155. -
    1156. $array_types[$tt] = 1;
    1157. -
    1158. // TODO: for literal, the name should be $name
    1159. -
    1160. $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
    1161. -
    1162. ++$i;
    1163. -
    1164. }
    1165. -
    1166. if(count($array_types) > 1){
    1167. -
    1168. $array_typename = 'xsd:anyType';
    1169. -
    1170. } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
    1171. -
    1172. if ($tt == 'integer') {
    1173. -
    1174. $tt = 'int';
    1175. -
    1176. }
    1177. -
    1178. $array_typename = 'xsd:'.$tt;
    1179. -
    1180. } elseif(isset($tt) && $tt == 'arraySimple'){
    1181. -
    1182. $array_typename = 'SOAP-ENC:Array';
    1183. -
    1184. } elseif(isset($tt) && $tt == 'arrayStruct'){
    1185. -
    1186. $array_typename = 'unnamed_struct_use_soapval';
    1187. -
    1188. } else {
    1189. -
    1190. // if type is prefixed, create type prefix
    1191. -
    1192. if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
    1193. -
    1194. $array_typename = 'xsd:' . $tt;
    1195. -
    1196. } elseif ($tt_ns) {
    1197. -
    1198. $tt_prefix = 'ns' . rand(1000, 9999);
    1199. -
    1200. $array_typename = "$tt_prefix:$tt";
    1201. -
    1202. $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
    1203. -
    1204. } else {
    1205. -
    1206. $array_typename = $tt;
    1207. -
    1208. }
    1209. -
    1210. }
    1211. -
    1212. $array_type = $i;
    1213. -
    1214. if ($use == 'literal') {
    1215. -
    1216. $type_str = '';
    1217. -
    1218. } else if (isset($type) && isset($type_prefix)) {
    1219. -
    1220. $type_str = " xsi:type=\"$type_prefix:$type\"";
    1221. -
    1222. } else {
    1223. -
    1224. $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
    1225. -
    1226. }
    1227. -
    1228. // empty array
    1229. -
    1230. } else {
    1231. -
    1232. if ($use == 'literal') {
    1233. -
    1234. $type_str = '';
    1235. -
    1236. } else if (isset($type) && isset($type_prefix)) {
    1237. -
    1238. $type_str = " xsi:type=\"$type_prefix:$type\"";
    1239. -
    1240. } else {
    1241. -
    1242. $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
    1243. -
    1244. }
    1245. -
    1246. }
    1247. -
    1248. // TODO: for array in literal, there is no wrapper here
    1249. -
    1250. $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
    1251. -
    1252. } else {
    1253. -
    1254. // got a struct
    1255. -
    1256. $this->debug("serialize_val: serialize struct");
    1257. -
    1258. if(isset($type) && isset($type_prefix)){
    1259. -
    1260. $type_str = " xsi:type=\"$type_prefix:$type\"";
    1261. -
    1262. } else {
    1263. -
    1264. $type_str = '';
    1265. -
    1266. }
    1267. -
    1268. if ($use == 'literal') {
    1269. -
    1270. $xml .= "<$name$xmlns$atts>";
    1271. -
    1272. } else {
    1273. -
    1274. $xml .= "<$name$xmlns$type_str$atts>";
    1275. -
    1276. }
    1277. -
    1278. foreach($val as $k => $v){
    1279. -
    1280. // Apache Map
    1281. -
    1282. if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
    1283. -
    1284. $xml .= '<item>';
    1285. -
    1286. $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
    1287. -
    1288. $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
    1289. -
    1290. $xml .= '</item>';
    1291. -
    1292. } else {
    1293. -
    1294. $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
    1295. -
    1296. }
    1297. -
    1298. }
    1299. -
    1300. $xml .= "</$name>";
    1301. -
    1302. }
    1303. -
    1304. break;
    1305. -
    1306. default:
    1307. -
    1308. $this->debug("serialize_val: serialize unknown");
    1309. -
    1310. $xml .= 'not detected, got '.gettype($val).' for '.$val;
    1311. -
    1312. break;
    1313. -
    1314. }
    1315. -
    1316. $this->debug("serialize_val returning $xml");
    1317. -
    1318. return $xml;
    1319. -
    1320. }
    1321. -
    1322.  
    1323. -
    1324. /**
    1325. -
    1326. * serializes a message
    1327. -
    1328. *
    1329. -
    1330. * @param string $body the XML of the SOAP body
    1331. -
    1332. * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
    1333. -
    1334. * @param array $namespaces optional the namespaces used in generating the body and headers
    1335. -
    1336. * @param string $style optional (rpc|document)
    1337. -
    1338. * @param string $use optional (encoded|literal)
    1339. -
    1340. * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
    1341. -
    1342. * @return string the message
    1343. -
    1344. * @access public
    1345. -
    1346. */
    1347. -
    1348. function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
    1349. -
    1350. // TODO: add an option to automatically run utf8_encode on $body and $headers
    1351. -
    1352. // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
    1353. -
    1354. // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
    1355. -
    1356.  
    1357. -
    1358. $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
    1359. -
    1360. $this->debug("headers:");
    1361. -
    1362. $this->appendDebug($this->varDump($headers));
    1363. -
    1364. $this->debug("namespaces:");
    1365. -
    1366. $this->appendDebug($this->varDump($namespaces));
    1367. -
    1368.  
    1369. -
    1370. // serialize namespaces
    1371. -
    1372. $ns_string = '';
    1373. -
    1374. foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
    1375. -
    1376. $ns_string .= " xmlns:$k=\"$v\"";
    1377. -
    1378. }
    1379. -
    1380. if($encodingStyle) {
    1381. -
    1382. $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
    1383. -
    1384. }
    1385. -
    1386.  
    1387. -
    1388. // serialize headers
    1389. -
    1390. if($headers){
    1391. -
    1392. if (is_array($headers)) {
    1393. -
    1394. $xml = '';
    1395. -
    1396. foreach ($headers as $k => $v) {
    1397. -
    1398. if (is_object($v) && get_class($v) == 'soapval') {
    1399. -
    1400. $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
    1401. -
    1402. } else {
    1403. -
    1404. $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
    1405. -
    1406. }
    1407. -
    1408. }
    1409. -
    1410. $headers = $xml;
    1411. -
    1412. $this->debug("In serializeEnvelope, serialized array of headers to $headers");
    1413. -
    1414. }
    1415. -
    1416. $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
    1417. -
    1418. }
    1419. -
    1420. // serialize envelope
    1421. -
    1422. return
    1423. -
    1424. '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
    1425. -
    1426. '<SOAP-ENV:Envelope'.$ns_string.">".
    1427. -
    1428. $headers.
    1429. -
    1430. "<SOAP-ENV:Body>".
    1431. -
    1432. $body.
    1433. -
    1434. "</SOAP-ENV:Body>".
    1435. -
    1436. "</SOAP-ENV:Envelope>";
    1437. -
    1438. }
    1439. -
    1440.  
    1441. -
    1442. /**
    1443. -
    1444. * formats a string to be inserted into an HTML stream
    1445. -
    1446. *
    1447. -
    1448. * @param string $str The string to format
    1449. -
    1450. * @return string The formatted string
    1451. -
    1452. * @access public
    1453. -
    1454. * @deprecated
    1455. -
    1456. */
    1457. -
    1458. function formatDump($str){
    1459. -
    1460. $str = htmlspecialchars($str);
    1461. -
    1462. return nl2br($str);
    1463. -
    1464. }
    1465. -
    1466.  
    1467. -
    1468. /**
    1469. -
    1470. * contracts (changes namespace to prefix) a qualified name
    1471. -
    1472. *
    1473. -
    1474. * @param string $qname qname
    1475. -
    1476. * @return string contracted qname
    1477. -
    1478. * @access private
    1479. -
    1480. */
    1481. -
    1482. function contractQname($qname){
    1483. -
    1484. // get element namespace
    1485. -
    1486. //$this->xdebug("Contract $qname");
    1487. -
    1488. if (strrpos($qname, ':')) {
    1489. -
    1490. // get unqualified name
    1491. -
    1492. $name = substr($qname, strrpos($qname, ':') + 1);
    1493. -
    1494. // get ns
    1495. -
    1496. $ns = substr($qname, 0, strrpos($qname, ':'));
    1497. -
    1498. $p = $this->getPrefixFromNamespace($ns);
    1499. -
    1500. if ($p) {
    1501. -
    1502. return $p . ':' . $name;
    1503. -
    1504. }
    1505. -
    1506. return $qname;
    1507. -
    1508. } else {
    1509. -
    1510. return $qname;
    1511. -
    1512. }
    1513. -
    1514. }
    1515. -
    1516.  
    1517. -
    1518. /**
    1519. -
    1520. * expands (changes prefix to namespace) a qualified name
    1521. -
    1522. *
    1523. -
    1524. * @param string $qname qname
    1525. -
    1526. * @return string expanded qname
    1527. -
    1528. * @access private
    1529. -
    1530. */
    1531. -
    1532. function expandQname($qname){
    1533. -
    1534. // get element prefix
    1535. -
    1536. if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
    1537. -
    1538. // get unqualified name
    1539. -
    1540. $name = substr(strstr($qname,':'),1);
    1541. -
    1542. // get ns prefix
    1543. -
    1544. $prefix = substr($qname,0,strpos($qname,':'));
    1545. -
    1546. if(isset($this->namespaces[$prefix])){
    1547. -
    1548. return $this->namespaces[$prefix].':'.$name;
    1549. -
    1550. } else {
    1551. -
    1552. return $qname;
    1553. -
    1554. }
    1555. -
    1556. } else {
    1557. -
    1558. return $qname;
    1559. -
    1560. }
    1561. -
    1562. }
    1563. -
    1564.  
    1565. -
    1566. /**
    1567. -
    1568. * returns the local part of a prefixed string
    1569. -
    1570. * returns the original string, if not prefixed
    1571. -
    1572. *
    1573. -
    1574. * @param string $str The prefixed string
    1575. -
    1576. * @return string The local part
    1577. -
    1578. * @access public
    1579. -
    1580. */
    1581. -
    1582. function getLocalPart($str){
    1583. -
    1584. if($sstr = strrchr($str,':')){
    1585. -
    1586. // get unqualified name
    1587. -
    1588. return substr( $sstr, 1 );
    1589. -
    1590. } else {
    1591. -
    1592. return $str;
    1593. -
    1594. }
    1595. -
    1596. }
    1597. -
    1598.  
    1599. -
    1600. /**
    1601. -
    1602. * returns the prefix part of a prefixed string
    1603. -
    1604. * returns false, if not prefixed
    1605. -
    1606. *
    1607. -
    1608. * @param string $str The prefixed string
    1609. -
    1610. * @return mixed The prefix or false if there is no prefix
    1611. -
    1612. * @access public
    1613. -
    1614. */
    1615. -
    1616. function getPrefix($str){
    1617. -
    1618. if($pos = strrpos($str,':')){
    1619. -
    1620. // get prefix
    1621. -
    1622. return substr($str,0,$pos);
    1623. -
    1624. }
    1625. -
    1626. return false;
    1627. -
    1628. }
    1629. -
    1630.  
    1631. -
    1632. /**
    1633. -
    1634. * pass it a prefix, it returns a namespace
    1635. -
    1636. *
    1637. -
    1638. * @param string $prefix The prefix
    1639. -
    1640. * @return mixed The namespace, false if no namespace has the specified prefix
    1641. -
    1642. * @access public
    1643. -
    1644. */
    1645. -
    1646. function getNamespaceFromPrefix($prefix){
    1647. -
    1648. if (isset($this->namespaces[$prefix])) {
    1649. -
    1650. return $this->namespaces[$prefix];
    1651. -
    1652. }
    1653. -
    1654. //$this->setError("No namespace registered for prefix '$prefix'");
    1655. -
    1656. return false;
    1657. -
    1658. }
    1659. -
    1660.  
    1661. -
    1662. /**
    1663. -
    1664. * returns the prefix for a given namespace (or prefix)
    1665. -
    1666. * or false if no prefixes registered for the given namespace
    1667. -
    1668. *
    1669. -
    1670. * @param string $ns The namespace
    1671. -
    1672. * @return mixed The prefix, false if the namespace has no prefixes
    1673. -
    1674. * @access public
    1675. -
    1676. */
    1677. -
    1678. function getPrefixFromNamespace($ns) {
    1679. -
    1680. foreach ($this->namespaces as $p => $n) {
    1681. -
    1682. if ($ns == $n || $ns == $p) {
    1683. -
    1684. $this->usedNamespaces[$p] = $n;
    1685. -
    1686. return $p;
    1687. -
    1688. }
    1689. -
    1690. }
    1691. -
    1692. return false;
    1693. -
    1694. }
    1695. -
    1696.  
    1697. -
    1698. /**
    1699. -
    1700. * returns the time in ODBC canonical form with microseconds
    1701. -
    1702. *
    1703. -
    1704. * @return string The time in ODBC canonical form with microseconds
    1705. -
    1706. * @access public
    1707. -
    1708. */
    1709. -
    1710. function getmicrotime() {
    1711. -
    1712. if (function_exists('gettimeofday')) {
    1713. -
    1714. $tod = gettimeofday();
    1715. -
    1716. $sec = $tod['sec'];
    1717. -
    1718. $usec = $tod['usec'];
    1719. -
    1720. } else {
    1721. -
    1722. $sec = time();
    1723. -
    1724. $usec = 0;
    1725. -
    1726. }
    1727. -
    1728. return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
    1729. -
    1730. }
    1731. -
    1732.  
    1733. -
    1734. /**
    1735. -
    1736. * Returns a string with the output of var_dump
    1737. -
    1738. *
    1739. -
    1740. * @param mixed $data The variable to var_dump
    1741. -
    1742. * @return string The output of var_dump
    1743. -
    1744. * @access public
    1745. -
    1746. */
    1747. -
    1748. function varDump($data) {
    1749. -
    1750. ob_start();
    1751. -
    1752. var_dump($data);
    1753. -
    1754. $ret_val = ob_get_contents();
    1755. -
    1756. ob_end_clean();
    1757. -
    1758. return $ret_val;
    1759. -
    1760. }
    1761. -
    1762.  
    1763. -
    1764. /**
    1765. -
    1766. * represents the object as a string
    1767. -
    1768. *
    1769. -
    1770. * @return string
    1771. -
    1772. * @access public
    1773. -
    1774. */
    1775. -
    1776. function __toString() {
    1777. -
    1778. return $this->varDump($this);
    1779. -
    1780. }
    1781. -
    1782. }
    1783. -
    1784.  
    1785. -
    1786. // XML Schema Datatype Helper Functions
    1787. -
    1788. //xsd:dateTime helpers
    1789. -
    1790.  
    1791. -
    1792.  
    1793. -
    1794.  
    1795. -
    1796. /**
    1797. -
    1798. * convert unix timestamp to ISO 8601 compliant date string
    1799. -
    1800. *
    1801. -
    1802. * @param int $timestamp Unix time stamp
    1803. -
    1804. * @param boolean $utc Whether the time stamp is UTC or local
    1805. -
    1806. * @return mixed ISO 8601 date string or false
    1807. -
    1808. * @access public
    1809. -
    1810. */
    1811. -
    1812. function timestamp_to_iso8601($timestamp,$utc=true){
    1813. -
    1814. $datestr = date('Y-m-d\TH:i:sO',$timestamp);
    1815. -
    1816. $pos = strrpos($datestr, "+");
    1817. -
    1818. if ($pos === FALSE) {
    1819. -
    1820. $pos = strrpos($datestr, "-");
    1821. -
    1822. }
    1823. -
    1824. if ($pos !== FALSE) {
    1825. -
    1826. if (strlen($datestr) == $pos + 5) {
    1827. -
    1828. $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
    1829. -
    1830. }
    1831. -
    1832. }
    1833. -
    1834. if($utc){
    1835. -
    1836. $pattern = '/'.
    1837. -
    1838. '([0-9]{4})-'. // centuries & years CCYY-
    1839. -
    1840. '([0-9]{2})-'. // months MM-
    1841. -
    1842. '([0-9]{2})'. // days DD
    1843. -
    1844. 'T'. // separator T
    1845. -
    1846. '([0-9]{2}):'. // hours hh:
    1847. -
    1848. '([0-9]{2}):'. // minutes mm:
    1849. -
    1850. '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
    1851. -
    1852. '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
    1853. -
    1854. '/';
    1855. -
    1856.  
    1857. -
    1858. if(preg_match($pattern,$datestr,$regs)){
    1859. -
    1860. return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
    1861. -
    1862. }
    1863. -
    1864. return false;
    1865. -
    1866. } else {
    1867. -
    1868. return $datestr;
    1869. -
    1870. }
    1871. -
    1872. }
    1873. -
    1874.  
    1875. -
    1876. /**
    1877. -
    1878. * convert ISO 8601 compliant date string to unix timestamp
    1879. -
    1880. *
    1881. -
    1882. * @param string $datestr ISO 8601 compliant date string
    1883. -
    1884. * @return mixed Unix timestamp (int) or false
    1885. -
    1886. * @access public
    1887. -
    1888. */
    1889. -
    1890. function iso8601_to_timestamp($datestr){
    1891. -
    1892. $pattern = '/'.
    1893. -
    1894. '([0-9]{4})-'. // centuries & years CCYY-
    1895. -
    1896. '([0-9]{2})-'. // months MM-
    1897. -
    1898. '([0-9]{2})'. // days DD
    1899. -
    1900. 'T'. // separator T
    1901. -
    1902. '([0-9]{2}):'. // hours hh:
    1903. -
    1904. '([0-9]{2}):'. // minutes mm:
    1905. -
    1906. '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
    1907. -
    1908. '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
    1909. -
    1910. '/';
    1911. -
    1912. if(preg_match($pattern,$datestr,$regs)){
    1913. -
    1914. // not utc
    1915. -
    1916. if($regs[8] != 'Z'){
    1917. -
    1918. $op = substr($regs[8],0,1);
    1919. -
    1920. $h = substr($regs[8],1,2);
    1921. -
    1922. $m = substr($regs[8],strlen($regs[8])-2,2);
    1923. -
    1924. if($op == '-'){
    1925. -
    1926. $regs[4] = $regs[4] + $h;
    1927. -
    1928. $regs[5] = $regs[5] + $m;
    1929. -
    1930. } elseif($op == '+'){
    1931. -
    1932. $regs[4] = $regs[4] - $h;
    1933. -
    1934. $regs[5] = $regs[5] - $m;
    1935. -
    1936. }
    1937. -
    1938. }
    1939. -
    1940. return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
    1941. -
    1942. // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
    1943. -
    1944. } else {
    1945. -
    1946. return false;
    1947. -
    1948. }
    1949. -
    1950. }
    1951. -
    1952.  
    1953. -
    1954. /**
    1955. -
    1956. * sleeps some number of microseconds
    1957. -
    1958. *
    1959. -
    1960. * @param string $usec the number of microseconds to sleep
    1961. -
    1962. * @access public
    1963. -
    1964. * @deprecated
    1965. -
    1966. */
    1967. -
    1968. function usleepWindows($usec)
    1969. -
    1970. {
    1971. -
    1972. $start = gettimeofday();
    1973. -
    1974. -
    1975. do
    1976. -
    1977. {
    1978. -
    1979. $stop = gettimeofday();
    1980. -
    1981. $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
    1982. -
    1983. + $stop['usec'] - $start['usec'];
    1984. -
    1985. }
    1986. -
    1987. while ($timePassed < $usec);
    1988. -
    1989. }
    1990. -
    1991.  
    1992. -
    1993. ?><?php
    1994. -
    1995.  
    1996. -
    1997.  
    1998. -
    1999.  
    2000. -
    2001. /**
    2002. -
    2003. * Contains information for a SOAP fault.
    2004. -
    2005. * Mainly used for returning faults from deployed functions
    2006. -
    2007. * in a server instance.
    2008. -
    2009. * @author Dietrich Ayala <dietrich@ganx4.com>
    2010. -
    2011. * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    2012. -
    2013. * @access public
    2014. -
    2015. */
    2016. -
    2017. class nusoap_fault extends nusoap_base {
    2018. -
    2019. /**
    2020. -
    2021. * The fault code (client|server)
    2022. -
    2023. * @var string
    2024. -
    2025. * @access private
    2026. -
    2027. */
    2028. -
    2029. var $faultcode;
    2030. -
    2031. /**
    2032. -
    2033. * The fault actor
    2034. -
    2035. * @var string
    2036. -
    2037. * @access private
    2038. -
    2039. */
    2040. -
    2041. var $faultactor;
    2042. -
    2043. /**
    2044. -
    2045. * The fault string, a description of the fault
    2046. -
    2047. * @var string
    2048. -
    2049. * @access private
    2050. -
    2051. */
    2052. -
    2053. var $faultstring;
    2054. -
    2055. /**
    2056. -
    2057. * The fault detail, typically a string or array of string
    2058. -
    2059. * @var mixed
    2060. -
    2061. * @access private
    2062. -
    2063. */
    2064. -
    2065. var $faultdetail;
    2066. -
    2067.  
    2068. -
    2069. /**
    2070. -
    2071. * constructor
    2072. -
    2073. *
    2074. -
    2075. * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
    2076. -
    2077. * @param string $faultactor only used when msg routed between multiple actors
    2078. -
    2079. * @param string $faultstring human readable error message
    2080. -
    2081. * @param mixed $faultdetail detail, typically a string or array of string
    2082. -
    2083. */
    2084. -
    2085. function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
    2086. -
    2087. parent::nusoap_base();
    2088. -
    2089. $this->faultcode = $faultcode;
    2090. -
    2091. $this->faultactor = $faultactor;
    2092. -
    2093. $this->faultstring = $faultstring;
    2094. -
    2095. $this->faultdetail = $faultdetail;
    2096. -
    2097. }
    2098. -
    2099.  
    2100. -
    2101. /**
    2102. -
    2103. * serialize a fault
    2104. -
    2105. *
    2106. -
    2107. * @return string The serialization of the fault instance.
    2108. -
    2109. * @access public
    2110. -
    2111. */
    2112. -
    2113. function serialize(){
    2114. -
    2115. $ns_string = '';
    2116. -
    2117. foreach($this->namespaces as $k => $v){
    2118. -
    2119. $ns_string .= "\n xmlns:$k=\"$v\"";
    2120. -
    2121. }
    2122. -
    2123. $return_msg =
    2124. -
    2125. '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
    2126. -
    2127. '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
    2128. -
    2129. '<SOAP-ENV:Body>'.
    2130. -
    2131. '<SOAP-ENV:Fault>'.
    2132. -
    2133. $this->serialize_val($this->faultcode, 'faultcode').
    2134. -
    2135. $this->serialize_val($this->faultactor, 'faultactor').
    2136. -
    2137. $this->serialize_val($this->faultstring, 'faultstring').
    2138. -
    2139. $this->serialize_val($this->faultdetail, 'detail').
    2140. -
    2141. '</SOAP-ENV:Fault>'.
    2142. -
    2143. '</SOAP-ENV:Body>'.
    2144. -
    2145. '</SOAP-ENV:Envelope>';
    2146. -
    2147. return $return_msg;
    2148. -
    2149. }
    2150. -
    2151. }
    2152. -
    2153.  
    2154. -
    2155. /**
    2156. -
    2157. * Backward compatibility
    2158. -
    2159. */
    2160. -
    2161. class soap_fault extends nusoap_fault {
    2162. -
    2163. }
    2164. -
    2165.  
    2166. -
    2167. ?><?php
    2168. -
    2169.  
    2170. -
    2171.  
    2172. -
    2173.  
    2174. -
    2175. /**
    2176. -
    2177. * parses an XML Schema, allows access to it's data, other utility methods.
    2178. -
    2179. * imperfect, no validation... yet, but quite functional.
    2180. -
    2181. *
    2182. -
    2183. * @author Dietrich Ayala <dietrich@ganx4.com>
    2184. -
    2185. * @author Scott Nichol <snichol@users.sourceforge.net>
    2186. -
    2187. * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    2188. -
    2189. * @access public
    2190. -
    2191. */
    2192. -
    2193. class nusoap_xmlschema extends nusoap_base {
    2194. -
    2195. -
    2196. // files
    2197. -
    2198. -
    2199. var $schema = '';
    2200. -
    2201. var $xml = '';
    2202. -
    2203. // namespaces
    2204. -
    2205. -
    2206. var $enclosingNamespaces;
    2207. -
    2208. // schema info
    2209. -
    2210. -
    2211. var $schemaInfo = array();
    2212. -
    2213. var $schemaTargetNamespace = '';
    2214. -
    2215. // types, elements, attributes defined by the schema
    2216. -
    2217. -
    2218. var $attributes = array();
    2219. -
    2220. var $complexTypes = array();
    2221. -
    2222. var $complexTypeStack = array();
    2223. -
    2224. var $currentComplexType = null;
    2225. -
    2226. var $elements = array();
    2227. -
    2228. var $elementStack = array();
    2229. -
    2230. var $currentElement = null;
    2231. -
    2232. var $simpleTypes = array();
    2233. -
    2234. var $simpleTypeStack = array();
    2235. -
    2236. var $currentSimpleType = null;
    2237. -
    2238. // imports
    2239. -
    2240. -
    2241. var $imports = array();
    2242. -
    2243. // parser vars
    2244. -
    2245. -
    2246. var $parser;
    2247. -
    2248. var $position = 0;
    2249. -
    2250. var $depth = 0;
    2251. -
    2252. var $depth_array = array();
    2253. -
    2254. var $message = array();
    2255. -
    2256. var $defaultNamespace = array();
    2257. -
    2258. -
    2259. /**
    2260. -
    2261. * constructor
    2262. -
    2263. *
    2264. -
    2265. * @param string $schema schema document URI
    2266. -
    2267. * @param string $xml xml document URI
    2268. -
    2269. * @param string $namespaces namespaces defined in enclosing XML
    2270. -
    2271. * @access public
    2272. -
    2273. */
    2274. -
    2275. function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
    2276. -
    2277. parent::nusoap_base();
    2278. -
    2279. $this->debug('nusoap_xmlschema class instantiated, inside constructor');
    2280. -
    2281. // files
    2282. -
    2283. $this->schema = $schema;
    2284. -
    2285. $this->xml = $xml;
    2286. -
    2287.  
    2288. -
    2289. // namespaces
    2290. -
    2291. $this->enclosingNamespaces = $namespaces;
    2292. -
    2293. $this->namespaces = array_merge($this->namespaces, $namespaces);
    2294. -
    2295.  
    2296. -
    2297. // parse schema file
    2298. -
    2299. if($schema != ''){
    2300. -
    2301. $this->debug('initial schema file: '.$schema);
    2302. -
    2303. $this->parseFile($schema, 'schema');
    2304. -
    2305. }
    2306. -
    2307.  
    2308. -
    2309. // parse xml file
    2310. -
    2311. if($xml != ''){
    2312. -
    2313. $this->debug('initial xml file: '.$xml);
    2314. -
    2315. $this->parseFile($xml, 'xml');
    2316. -
    2317. }
    2318. -
    2319.  
    2320. -
    2321. }
    2322. -
    2323.  
    2324. -
    2325. /**
    2326. -
    2327. * parse an XML file
    2328. -
    2329. *
    2330. -
    2331. * @param string $xml path/URL to XML file
    2332. -
    2333. * @param string $type (schema | xml)
    2334. -
    2335. * @return boolean
    2336. -
    2337. * @access public
    2338. -
    2339. */
    2340. -
    2341. function parseFile($xml,$type){
    2342. -
    2343. // parse xml file
    2344. -
    2345. if($xml != ""){
    2346. -
    2347. $xmlStr = @join("",@file($xml));
    2348. -
    2349. if($xmlStr == ""){
    2350. -
    2351. $msg = 'Error reading XML from '.$xml;
    2352. -
    2353. $this->setError($msg);
    2354. -
    2355. $this->debug($msg);
    2356. -
    2357. return false;
    2358. -
    2359. } else {
    2360. -
    2361. $this->debug("parsing $xml");
    2362. -
    2363. $this->parseString($xmlStr,$type);
    2364. -
    2365. $this->debug("done parsing $xml");
    2366. -
    2367. return true;
    2368. -
    2369. }
    2370. -
    2371. }
    2372. -
    2373. return false;
    2374. -
    2375. }
    2376. -
    2377.  
    2378. -
    2379. /**
    2380. -
    2381. * parse an XML string
    2382. -
    2383. *
    2384. -
    2385. * @param string $xml path or URL
    2386. -
    2387. * @param string $type (schema|xml)
    2388. -
    2389. * @access private
    2390. -
    2391. */
    2392. -
    2393. function parseString($xml,$type){
    2394. -
    2395. // parse xml string
    2396. -
    2397. if($xml != ""){
    2398. -
    2399.  
    2400. -
    2401. // Create an XML parser.
    2402. -
    2403. $this->parser = xml_parser_create();
    2404. -
    2405. // Set the options for parsing the XML data.
    2406. -
    2407. xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
    2408. -
    2409.  
    2410. -
    2411. // Set the object for the parser.
    2412. -
    2413. xml_set_object($this->parser, $this);
    2414. -
    2415.  
    2416. -
    2417. // Set the element handlers for the parser.
    2418. -
    2419. if($type == "schema"){
    2420. -
    2421. xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
    2422. -
    2423. xml_set_character_data_handler($this->parser,'schemaCharacterData');
    2424. -
    2425. } elseif($type == "xml"){
    2426. -
    2427. xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
    2428. -
    2429. xml_set_character_data_handler($this->parser,'xmlCharacterData');
    2430. -
    2431. }
    2432. -
    2433.  
    2434. -
    2435. // Parse the XML file.
    2436. -
    2437. if(!xml_parse($this->parser,$xml,true)){
    2438. -
    2439. // Display an error message.
    2440. -
    2441. $errstr = sprintf('XML error parsing XML schema on line %d: %s',
    2442. -
    2443. xml_get_current_line_number($this->parser),
    2444. -
    2445. xml_error_string(xml_get_error_code($this->parser))
    2446. -
    2447. );
    2448. -
    2449. $this->debug($errstr);
    2450. -
    2451. $this->debug("XML payload:\n" . $xml);
    2452. -
    2453. $this->setError($errstr);
    2454. -
    2455. }
    2456. -
    2457. -
    2458. xml_parser_free($this->parser);
    2459. -
    2460. } else{
    2461. -
    2462. $this->debug('no xml passed to parseString()!!');
    2463. -
    2464. $this->setError('no xml passed to parseString()!!');
    2465. -
    2466. }
    2467. -
    2468. }
    2469. -
    2470.  
    2471. -
    2472. /**
    2473. -
    2474. * gets a type name for an unnamed type
    2475. -
    2476. *
    2477. -
    2478. * @param string Element name
    2479. -
    2480. * @return string A type name for an unnamed type
    2481. -
    2482. * @access private
    2483. -
    2484. */
    2485. -
    2486. function CreateTypeName($ename) {
    2487. -
    2488. $scope = '';
    2489. -
    2490. for ($i = 0; $i < count($this->complexTypeStack); $i++) {
    2491. -
    2492. $scope .= $this->complexTypeStack[$i] . '_';
    2493. -
    2494. }
    2495. -
    2496. return $scope . $ename . '_ContainedType';
    2497. -
    2498. }
    2499. -
    2500. -
    2501. /**
    2502. -
    2503. * start-element handler
    2504. -
    2505. *
    2506. -
    2507. * @param string $parser XML parser object
    2508. -
    2509. * @param string $name element name
    2510. -
    2511. * @param string $attrs associative array of attributes
    2512. -
    2513. * @access private
    2514. -
    2515. */
    2516. -
    2517. function schemaStartElement($parser, $name, $attrs) {
    2518. -
    2519. -
    2520. // position in the total number of elements, starting from 0
    2521. -
    2522. $pos = $this->position++;
    2523. -
    2524. $depth = $this->depth++;
    2525. -
    2526. // set self as current value for this depth
    2527. -
    2528. $this->depth_array[$depth] = $pos;
    2529. -
    2530. $this->message[$pos] = array('cdata' => '');
    2531. -
    2532. if ($depth > 0) {
    2533. -
    2534. $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
    2535. -
    2536. } else {
    2537. -
    2538. $this->defaultNamespace[$pos] = false;
    2539. -
    2540. }
    2541. -
    2542.  
    2543. -
    2544. // get element prefix
    2545. -
    2546. if($prefix = $this->getPrefix($name)){
    2547. -
    2548. // get unqualified name
    2549. -
    2550. $name = $this->getLocalPart($name);
    2551. -
    2552. } else {
    2553. -
    2554. $prefix = '';
    2555. -
    2556. }
    2557. -
    2558. -
    2559. // loop thru attributes, expanding, and registering namespace declarations
    2560. -
    2561. if(count($attrs) > 0){
    2562. -
    2563. foreach($attrs as $k => $v){
    2564. -
    2565. // if ns declarations, add to class level array of valid namespaces
    2566. -
    2567. if(preg_match('/^xmlns/',$k)){
    2568. -
    2569. //$this->xdebug("$k: $v");
    2570. -
    2571. //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
    2572. -
    2573. if($ns_prefix = substr(strrchr($k,':'),1)){
    2574. -
    2575. //$this->xdebug("Add namespace[$ns_prefix] = $v");
    2576. -
    2577. $this->namespaces[$ns_prefix] = $v;
    2578. -
    2579. } else {
    2580. -
    2581. $this->defaultNamespace[$pos] = $v;
    2582. -
    2583. if (! $this->getPrefixFromNamespace($v)) {
    2584. -
    2585. $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
    2586. -
    2587. }
    2588. -
    2589. }
    2590. -
    2591. if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
    2592. -
    2593. $this->XMLSchemaVersion = $v;
    2594. -
    2595. $this->namespaces['xsi'] = $v.'-instance';
    2596. -
    2597. }
    2598. -
    2599. }
    2600. -
    2601. }
    2602. -
    2603. foreach($attrs as $k => $v){
    2604. -
    2605. // expand each attribute
    2606. -
    2607. $k = strpos($k,':') ? $this->expandQname($k) : $k;
    2608. -
    2609. $v = strpos($v,':') ? $this->expandQname($v) : $v;
    2610. -
    2611. $eAttrs[$k] = $v;
    2612. -
    2613. }
    2614. -
    2615. $attrs = $eAttrs;
    2616. -
    2617. } else {
    2618. -
    2619. $attrs = array();
    2620. -
    2621. }
    2622. -
    2623. // find status, register data
    2624. -
    2625. switch($name){
    2626. -
    2627. case 'all': // (optional) compositor content for a complexType
    2628. -
    2629. case 'choice':
    2630. -
    2631. case 'group':
    2632. -
    2633. case 'sequence':
    2634. -
    2635. //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
    2636. -
    2637. $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
    2638. -
    2639. //if($name == 'all' || $name == 'sequence'){
    2640. -
    2641. // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
    2642. -
    2643. //}
    2644. -
    2645. break;
    2646. -
    2647. case 'attribute': // complexType attribute
    2648. -
    2649. //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
    2650. -
    2651. $this->xdebug("parsing attribute:");
    2652. -
    2653. $this->appendDebug($this->varDump($attrs));
    2654. -
    2655. if (!isset($attrs['form'])) {
    2656. -
    2657. // TODO: handle globals
    2658. -
    2659. $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
    2660. -
    2661. }
    2662. -
    2663. if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
    2664. -
    2665. $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
    2666. -
    2667. if (!strpos($v, ':')) {
    2668. -
    2669. // no namespace in arrayType attribute value...
    2670. -
    2671. if ($this->defaultNamespace[$pos]) {
    2672. -
    2673. // ...so use the default
    2674. -
    2675. $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
    2676. -
    2677. }
    2678. -
    2679. }
    2680. -
    2681. }
    2682. -
    2683. if(isset($attrs['name'])){
    2684. -
    2685. $this->attributes[$attrs['name']] = $attrs;
    2686. -
    2687. $aname = $attrs['name'];
    2688. -
    2689. } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
    2690. -
    2691. if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
    2692. -
    2693. $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
    2694. -
    2695. } else {
    2696. -
    2697. $aname = '';
    2698. -
    2699. }
    2700. -
    2701. } elseif(isset($attrs['ref'])){
    2702. -
    2703. $aname = $attrs['ref'];
    2704. -
    2705. $this->attributes[$attrs['ref']] = $attrs;
    2706. -
    2707. }
    2708. -
    2709. -
    2710. if($this->currentComplexType){ // This should *always* be
    2711. -
    2712. $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
    2713. -
    2714. }
    2715. -
    2716. // arrayType attribute
    2717. -
    2718. if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
    2719. -
    2720. $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
    2721. -
    2722. $prefix = $this->getPrefix($aname);
    2723. -
    2724. if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
    2725. -
    2726. $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
    2727. -
    2728. } else {
    2729. -
    2730. $v = '';
    2731. -
    2732. }
    2733. -
    2734. if(strpos($v,'[,]')){
    2735. -
    2736. $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
    2737. -
    2738. }
    2739. -
    2740. $v = substr($v,0,strpos($v,'[')); // clip the []
    2741. -
    2742. if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
    2743. -
    2744. $v = $this->XMLSchemaVersion.':'.$v;
    2745. -
    2746. }
    2747. -
    2748. $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
    2749. -
    2750. }
    2751. -
    2752. break;
    2753. -
    2754. case 'complexContent': // (optional) content for a complexType
    2755. -
    2756. $this->xdebug("do nothing for element $name");
    2757. -
    2758. break;
    2759. -
    2760. case 'complexType':
    2761. -
    2762. array_push($this->complexTypeStack, $this->currentComplexType);
    2763. -
    2764. if(isset($attrs['name'])){
    2765. -
    2766. // TODO: what is the scope of named complexTypes that appear
    2767. -
    2768. // nested within other c complexTypes?
    2769. -
    2770. $this->xdebug('processing named complexType '.$attrs['name']);
    2771. -
    2772. //$this->currentElement = false;
    2773. -
    2774. $this->currentComplexType = $attrs['name'];
    2775. -
    2776. $this->complexTypes[$this->currentComplexType] = $attrs;
    2777. -
    2778. $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
    2779. -
    2780. // This is for constructs like
    2781. -
    2782. // <complexType name="ListOfString" base="soap:Array">
    2783. -
    2784. // <sequence>
    2785. -
    2786. // <element name="string" type="xsd:string"
    2787. -
    2788. // minOccurs="0" maxOccurs="unbounded" />
    2789. -
    2790. // </sequence>
    2791. -
    2792. // </complexType>
    2793. -
    2794. if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
    2795. -
    2796. $this->xdebug('complexType is unusual array');
    2797. -
    2798. $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
    2799. -
    2800. } else {
    2801. -
    2802. $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
    2803. -
    2804. }
    2805. -
    2806. } else {
    2807. -
    2808. $name = $this->CreateTypeName($this->currentElement);
    2809. -
    2810. $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
    2811. -
    2812. $this->currentComplexType = $name;
    2813. -
    2814. //$this->currentElement = false;
    2815. -
    2816. $this->complexTypes[$this->currentComplexType] = $attrs;
    2817. -
    2818. $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
    2819. -
    2820. // This is for constructs like
    2821. -
    2822. // <complexType name="ListOfString" base="soap:Array">
    2823. -
    2824. // <sequence>
    2825. -
    2826. // <element name="string" type="xsd:string"
    2827. -
    2828. // minOccurs="0" maxOccurs="unbounded" />
    2829. -
    2830. // </sequence>
    2831. -
    2832. // </complexType>
    2833. -
    2834. if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
    2835. -
    2836. $this->xdebug('complexType is unusual array');
    2837. -
    2838. $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
    2839. -
    2840. } else {
    2841. -
    2842. $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
    2843. -
    2844. }
    2845. -
    2846. }
    2847. -
    2848. $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false';
    2849. -
    2850. break;
    2851. -
    2852. case 'element':
    2853. -
    2854. array_push($this->elementStack, $this->currentElement);
    2855. -
    2856. if (!isset($attrs['form'])) {
    2857. -
    2858. if ($this->currentComplexType) {
    2859. -
    2860. $attrs['form'] = $this->schemaInfo['elementFormDefault'];
    2861. -
    2862. } else {
    2863. -
    2864. // global
    2865. -
    2866. $attrs['form'] = 'qualified';
    2867. -
    2868. }
    2869. -
    2870. }
    2871. -
    2872. if(isset($attrs['type'])){
    2873. -
    2874. $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
    2875. -
    2876. if (! $this->getPrefix($attrs['type'])) {
    2877. -
    2878. if ($this->defaultNamespace[$pos]) {
    2879. -
    2880. $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
    2881. -
    2882. $this->xdebug('used default namespace to make type ' . $attrs['type']);
    2883. -
    2884. }
    2885. -
    2886. }
    2887. -
    2888. // This is for constructs like
    2889. -
    2890. // <complexType name="ListOfString" base="soap:Array">
    2891. -
    2892. // <sequence>
    2893. -
    2894. // <element name="string" type="xsd:string"
    2895. -
    2896. // minOccurs="0" maxOccurs="unbounded" />
    2897. -
    2898. // </sequence>
    2899. -
    2900. // </complexType>
    2901. -
    2902. if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
    2903. -
    2904. $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
    2905. -
    2906. $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
    2907. -
    2908. }
    2909. -
    2910. $this->currentElement = $attrs['name'];
    2911. -
    2912. $ename = $attrs['name'];
    2913. -
    2914. } elseif(isset($attrs['ref'])){
    2915. -
    2916. $this->xdebug("processing element as ref to ".$attrs['ref']);
    2917. -
    2918. $this->currentElement = "ref to ".$attrs['ref'];
    2919. -
    2920. $ename = $this->getLocalPart($attrs['ref']);
    2921. -
    2922. } else {
    2923. -
    2924. $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
    2925. -
    2926. $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
    2927. -
    2928. $this->currentElement = $attrs['name'];
    2929. -
    2930. $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
    2931. -
    2932. $ename = $attrs['name'];
    2933. -
    2934. }
    2935. -
    2936. if (isset($ename) && $this->currentComplexType) {
    2937. -
    2938. $this->xdebug("add element $ename to complexType $this->currentComplexType");
    2939. -
    2940. $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
    2941. -
    2942. } elseif (!isset($attrs['ref'])) {
    2943. -
    2944. $this->xdebug("add element $ename to elements array");
    2945. -
    2946. $this->elements[ $attrs['name'] ] = $attrs;
    2947. -
    2948. $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
    2949. -
    2950. }
    2951. -
    2952. break;
    2953. -
    2954. case 'enumeration': // restriction value list member
    2955. -
    2956. $this->xdebug('enumeration ' . $attrs['value']);
    2957. -
    2958. if ($this->currentSimpleType) {
    2959. -
    2960. $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
    2961. -
    2962. } elseif ($this->currentComplexType) {
    2963. -
    2964. $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
    2965. -
    2966. }
    2967. -
    2968. break;
    2969. -
    2970. case 'extension': // simpleContent or complexContent type extension
    2971. -
    2972. $this->xdebug('extension ' . $attrs['base']);
    2973. -
    2974. if ($this->currentComplexType) {
    2975. -
    2976. $ns = $this->getPrefix($attrs['base']);
    2977. -
    2978. if ($ns == '') {
    2979. -
    2980. $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
    2981. -
    2982. } else {
    2983. -
    2984. $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
    2985. -
    2986. }
    2987. -
    2988. } else {
    2989. -
    2990. $this->xdebug('no current complexType to set extensionBase');
    2991. -
    2992. }
    2993. -
    2994. break;
    2995. -
    2996. case 'import':
    2997. -
    2998. if (isset($attrs['schemaLocation'])) {
    2999. -
    3000. $this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
    3001. -
    3002. $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
    3003. -
    3004. } else {
    3005. -
    3006. $this->xdebug('import namespace ' . $attrs['namespace']);
    3007. -
    3008. $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
    3009. -
    3010. if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
    3011. -
    3012. $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
    3013. -
    3014. }
    3015. -
    3016. }
    3017. -
    3018. break;
    3019. -
    3020. case 'include':
    3021. -
    3022. if (isset($attrs['schemaLocation'])) {
    3023. -
    3024. $this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
    3025. -
    3026. $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
    3027. -
    3028. } else {
    3029. -
    3030. $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
    3031. -
    3032. }
    3033. -
    3034. break;
    3035. -
    3036. case 'list': // simpleType value list
    3037. -
    3038. $this->xdebug("do nothing for element $name");
    3039. -
    3040. break;
    3041. -
    3042. case 'restriction': // simpleType, simpleContent or complexContent value restriction
    3043. -
    3044. $this->xdebug('restriction ' . $attrs['base']);
    3045. -
    3046. if($this->currentSimpleType){
    3047. -
    3048. $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
    3049. -
    3050. } elseif($this->currentComplexType){
    3051. -
    3052. $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
    3053. -
    3054. if(strstr($attrs['base'],':') == ':Array'){
    3055. -
    3056. $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
    3057. -
    3058. }
    3059. -
    3060. }
    3061. -
    3062. break;
    3063. -
    3064. case 'schema':
    3065. -
    3066. $this->schemaInfo = $attrs;
    3067. -
    3068. $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
    3069. -
    3070. if (isset($attrs['targetNamespace'])) {
    3071. -
    3072. $this->schemaTargetNamespace = $attrs['targetNamespace'];
    3073. -
    3074. }
    3075. -
    3076. if (!isset($attrs['elementFormDefault'])) {
    3077. -
    3078. $this->schemaInfo['elementFormDefault'] = 'unqualified';
    3079. -
    3080. }
    3081. -
    3082. if (!isset($attrs['attributeFormDefault'])) {
    3083. -
    3084. $this->schemaInfo['attributeFormDefault'] = 'unqualified';
    3085. -
    3086. }
    3087. -
    3088. break;
    3089. -
    3090. case 'simpleContent': // (optional) content for a complexType
    3091. -
    3092. if ($this->currentComplexType) { // This should *always* be
    3093. -
    3094. $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true';
    3095. -
    3096. } else {
    3097. -
    3098. $this->xdebug("do nothing for element $name because there is no current complexType");
    3099. -
    3100. }
    3101. -
    3102. break;
    3103. -
    3104. case 'simpleType':
    3105. -
    3106. array_push($this->simpleTypeStack, $this->currentSimpleType);
    3107. -
    3108. if(isset($attrs['name'])){
    3109. -
    3110. $this->xdebug("processing simpleType for name " . $attrs['name']);
    3111. -
    3112. $this->currentSimpleType = $attrs['name'];
    3113. -
    3114. $this->simpleTypes[ $attrs['name'] ] = $attrs;
    3115. -
    3116. $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
    3117. -
    3118. $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
    3119. -
    3120. } else {
    3121. -
    3122. $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
    3123. -
    3124. $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
    3125. -
    3126. $this->currentSimpleType = $name;
    3127. -
    3128. //$this->currentElement = false;
    3129. -
    3130. $this->simpleTypes[$this->currentSimpleType] = $attrs;
    3131. -
    3132. $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
    3133. -
    3134. }
    3135. -
    3136. break;
    3137. -
    3138. case 'union': // simpleType type list
    3139. -
    3140. $this->xdebug("do nothing for element $name");
    3141. -
    3142. break;
    3143. -
    3144. default:
    3145. -
    3146. $this->xdebug("do not have any logic to process element $name");
    3147. -
    3148. }
    3149. -
    3150. }
    3151. -
    3152.  
    3153. -
    3154. /**
    3155. -
    3156. * end-element handler
    3157. -
    3158. *
    3159. -
    3160. * @param string $parser XML parser object
    3161. -
    3162. * @param string $name element name
    3163. -
    3164. * @access private
    3165. -
    3166. */
    3167. -
    3168. function schemaEndElement($parser, $name) {
    3169. -
    3170. // bring depth down a notch
    3171. -
    3172. $this->depth--;
    3173. -
    3174. // position of current element is equal to the last value left in depth_array for my depth
    3175. -
    3176. if(isset($this->depth_array[$this->depth])){
    3177. -
    3178. $pos = $this->depth_array[$this->depth];
    3179. -
    3180. }
    3181. -
    3182. // get element prefix
    3183. -
    3184. if ($prefix = $this->getPrefix($name)){
    3185. -
    3186. // get unqualified name
    3187. -
    3188. $name = $this->getLocalPart($name);
    3189. -
    3190. } else {
    3191. -
    3192. $prefix = '';
    3193. -
    3194. }
    3195. -
    3196. // move on...
    3197. -
    3198. if($name == 'complexType'){
    3199. -
    3200. $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
    3201. -
    3202. $this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType]));
    3203. -
    3204. $this->currentComplexType = array_pop($this->complexTypeStack);
    3205. -
    3206. //$this->currentElement = false;
    3207. -
    3208. }
    3209. -
    3210. if($name == 'element'){
    3211. -
    3212. $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
    3213. -
    3214. $this->currentElement = array_pop($this->elementStack);
    3215. -
    3216. }
    3217. -
    3218. if($name == 'simpleType'){
    3219. -
    3220. $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
    3221. -
    3222. $this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType]));
    3223. -
    3224. $this->currentSimpleType = array_pop($this->simpleTypeStack);
    3225. -
    3226. }
    3227. -
    3228. }
    3229. -
    3230.  
    3231. -
    3232. /**
    3233. -
    3234. * element content handler
    3235. -
    3236. *
    3237. -
    3238. * @param string $parser XML parser object
    3239. -
    3240. * @param string $data element content
    3241. -
    3242. * @access private
    3243. -
    3244. */
    3245. -
    3246. function schemaCharacterData($parser, $data){
    3247. -
    3248. $pos = $this->depth_array[$this->depth - 1];
    3249. -
    3250. $this->message[$pos]['cdata'] .= $data;
    3251. -
    3252. }
    3253. -
    3254.  
    3255. -
    3256. /**
    3257. -
    3258. * serialize the schema
    3259. -
    3260. *
    3261. -
    3262. * @access public
    3263. -
    3264. */
    3265. -
    3266. function serializeSchema(){
    3267. -
    3268.  
    3269. -
    3270. $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
    3271. -
    3272. $xml = '';
    3273. -
    3274. // imports
    3275. -
    3276. if (sizeof($this->imports) > 0) {
    3277. -
    3278. foreach($this->imports as $ns => $list) {
    3279. -
    3280. foreach ($list as $ii) {
    3281. -
    3282. if ($ii['location'] != '') {
    3283. -
    3284. $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
    3285. -
    3286. } else {
    3287. -
    3288. $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
    3289. -
    3290. }
    3291. -
    3292. }
    3293. -
    3294. }
    3295. -
    3296. }
    3297. -
    3298. // complex types
    3299. -
    3300. foreach($this->complexTypes as $typeName => $attrs){
    3301. -
    3302. $contentStr = '';
    3303. -
    3304. // serialize child elements
    3305. -
    3306. if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
    3307. -
    3308. foreach($attrs['elements'] as $element => $eParts){
    3309. -
    3310. if(isset($eParts['ref'])){
    3311. -
    3312. $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
    3313. -
    3314. } else {
    3315. -
    3316. $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
    3317. -
    3318. foreach ($eParts as $aName => $aValue) {
    3319. -
    3320. // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
    3321. -
    3322. if ($aName != 'name' && $aName != 'type') {
    3323. -
    3324. $contentStr .= " $aName=\"$aValue\"";
    3325. -
    3326. }
    3327. -
    3328. }
    3329. -
    3330. $contentStr .= "/>\n";
    3331. -
    3332. }
    3333. -
    3334. }
    3335. -
    3336. // compositor wraps elements
    3337. -
    3338. if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
    3339. -
    3340. $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
    3341. -
    3342. }
    3343. -
    3344. }
    3345. -
    3346. // attributes
    3347. -
    3348. if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
    3349. -
    3350. foreach($attrs['attrs'] as $attr => $aParts){
    3351. -
    3352. $contentStr .= " <$schemaPrefix:attribute";
    3353. -
    3354. foreach ($aParts as $a => $v) {
    3355. -
    3356. if ($a == 'ref' || $a == 'type') {
    3357. -
    3358. $contentStr .= " $a=\"".$this->contractQName($v).'"';
    3359. -
    3360. } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
    3361. -
    3362. $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
    3363. -
    3364. $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
    3365. -
    3366. } else {
    3367. -
    3368. $contentStr .= " $a=\"$v\"";
    3369. -
    3370. }
    3371. -
    3372. }
    3373. -
    3374. $contentStr .= "/>\n";
    3375. -
    3376. }
    3377. -
    3378. }
    3379. -
    3380. // if restriction
    3381. -
    3382. if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
    3383. -
    3384. $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";
    3385. -
    3386. // complex or simple content
    3387. -
    3388. if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
    3389. -
    3390. $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
    3391. -
    3392. }
    3393. -
    3394. }
    3395. -
    3396. // finalize complex type
    3397. -
    3398. if($contentStr != ''){
    3399. -
    3400. $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
    3401. -
    3402. } else {
    3403. -
    3404. $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
    3405. -
    3406. }
    3407. -
    3408. $xml .= $contentStr;
    3409. -
    3410. }
    3411. -
    3412. // simple types
    3413. -
    3414. if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
    3415. -
    3416. foreach($this->simpleTypes as $typeName => $eParts){
    3417. -
    3418. $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
    3419. -
    3420. if (isset($eParts['enumeration'])) {
    3421. -
    3422. foreach ($eParts['enumeration'] as $e) {
    3423. -
    3424. $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
    3425. -
    3426. }
    3427. -
    3428. }
    3429. -
    3430. $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
    3431. -
    3432. }
    3433. -
    3434. }
    3435. -
    3436. // elements
    3437. -
    3438. if(isset($this->elements) && count($this->elements) > 0){
    3439. -
    3440. foreach($this->elements as $element => $eParts){
    3441. -
    3442. $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
    3443. -
    3444. }
    3445. -
    3446. }
    3447. -
    3448. // attributes
    3449. -
    3450. if(isset($this->attributes) && count($this->attributes) > 0){
    3451. -
    3452. foreach($this->attributes as $attr => $aParts){
    3453. -
    3454. $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
    3455. -
    3456. }
    3457. -
    3458. }
    3459. -
    3460. // finish 'er up
    3461. -
    3462. $attr = '';
    3463. -
    3464. foreach ($this->schemaInfo as $k => $v) {
    3465. -
    3466. if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
    3467. -
    3468. $attr .= " $k=\"$v\"";
    3469. -
    3470. }
    3471. -
    3472. }
    3473. -
    3474. $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
    3475. -
    3476. foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
    3477. -
    3478. $el .= " xmlns:$nsp=\"$ns\"";
    3479. -
    3480. }
    3481. -
    3482. $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
    3483. -
    3484. return $xml;
    3485. -
    3486. }
    3487. -
    3488.  
    3489. -
    3490. /**
    3491. -
    3492. * adds debug data to the clas level debug string
    3493. -
    3494. *
    3495. -
    3496. * @param string $string debug data
    3497. -
    3498. * @access private
    3499. -
    3500. */
    3501. -
    3502. function xdebug($string){
    3503. -
    3504. $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
    3505. -
    3506. }
    3507. -
    3508.  
    3509. -
    3510. /**
    3511. -
    3512. * get the PHP type of a user defined type in the schema
    3513. -
    3514. * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
    3515. -
    3516. * returns false if no type exists, or not w/ the given namespace
    3517. -
    3518. * else returns a string that is either a native php type, or 'struct'
    3519. -
    3520. *
    3521. -
    3522. * @param string $type name of defined type
    3523. -
    3524. * @param string $ns namespace of type
    3525. -
    3526. * @return mixed
    3527. -
    3528. * @access public
    3529. -
    3530. * @deprecated
    3531. -
    3532. */
    3533. -
    3534. function getPHPType($type,$ns){
    3535. -
    3536. if(isset($this->typemap[$ns][$type])){
    3537. -
    3538. //print "found type '$type' and ns $ns in typemap<br>";
    3539. -
    3540. return $this->typemap[$ns][$type];
    3541. -
    3542. } elseif(isset($this->complexTypes[$type])){
    3543. -
    3544. //print "getting type '$type' and ns $ns from complexTypes array<br>";
    3545. -
    3546. return $this->complexTypes[$type]['phpType'];
    3547. -
    3548. }
    3549. -
    3550. return false;
    3551. -
    3552. }
    3553. -
    3554.  
    3555. -
    3556. /**
    3557. -
    3558. * returns an associative array of information about a given type
    3559. -
    3560. * returns false if no type exists by the given name
    3561. -
    3562. *
    3563. -
    3564. * For a complexType typeDef = array(
    3565. -
    3566. * 'restrictionBase' => '',
    3567. -
    3568. * 'phpType' => '',
    3569. -
    3570. * 'compositor' => '(sequence|all)',
    3571. -
    3572. * 'elements' => array(), // refs to elements array
    3573. -
    3574. * 'attrs' => array() // refs to attributes array
    3575. -
    3576. * ... and so on (see addComplexType)
    3577. -
    3578. * )
    3579. -
    3580. *
    3581. -
    3582. * For simpleType or element, the array has different keys.
    3583. -
    3584. *
    3585. -
    3586. * @param string $type
    3587. -
    3588. * @return mixed
    3589. -
    3590. * @access public
    3591. -
    3592. * @see addComplexType
    3593. -
    3594. * @see addSimpleType
    3595. -
    3596. * @see addElement
    3597. -
    3598. */
    3599. -
    3600. function getTypeDef($type){
    3601. -
    3602. //$this->debug("in getTypeDef for type $type");
    3603. -
    3604. if (substr($type, -1) == '^') {
    3605. -
    3606. $is_element = 1;
    3607. -
    3608. $type = substr($type, 0, -1);
    3609. -
    3610. } else {
    3611. -
    3612. $is_element = 0;
    3613. -
    3614. }
    3615. -
    3616.  
    3617. -
    3618. if((! $is_element) && isset($this->complexTypes[$type])){
    3619. -
    3620. $this->xdebug("in getTypeDef, found complexType $type");
    3621. -
    3622. return $this->complexTypes[$type];
    3623. -
    3624. } elseif((! $is_element) && isset($this->simpleTypes[$type])){
    3625. -
    3626. $this->xdebug("in getTypeDef, found simpleType $type");
    3627. -
    3628. if (!isset($this->simpleTypes[$type]['phpType'])) {
    3629. -
    3630. // get info for type to tack onto the simple type
    3631. -
    3632. // TODO: can this ever really apply (i.e. what is a simpleType really?)
    3633. -
    3634. $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
    3635. -
    3636. $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
    3637. -
    3638. $etype = $this->getTypeDef($uqType);
    3639. -
    3640. if ($etype) {
    3641. -
    3642. $this->xdebug("in getTypeDef, found type for simpleType $type:");
    3643. -
    3644. $this->xdebug($this->varDump($etype));
    3645. -
    3646. if (isset($etype['phpType'])) {
    3647. -
    3648. $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
    3649. -
    3650. }
    3651. -
    3652. if (isset($etype['elements'])) {
    3653. -
    3654. $this->simpleTypes[$type]['elements'] = $etype['elements'];
    3655. -
    3656. }
    3657. -
    3658. }
    3659. -
    3660. }
    3661. -
    3662. return $this->simpleTypes[$type];
    3663. -
    3664. } elseif(isset($this->elements[$type])){
    3665. -
    3666. $this->xdebug("in getTypeDef, found element $type");
    3667. -
    3668. if (!isset($this->elements[$type]['phpType'])) {
    3669. -
    3670. // get info for type to tack onto the element
    3671. -
    3672. $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
    3673. -
    3674. $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
    3675. -
    3676. $etype = $this->getTypeDef($uqType);
    3677. -
    3678. if ($etype) {
    3679. -
    3680. $this->xdebug("in getTypeDef, found type for element $type:");
    3681. -
    3682. $this->xdebug($this->varDump($etype));
    3683. -
    3684. if (isset($etype['phpType'])) {
    3685. -
    3686. $this->elements[$type]['phpType'] = $etype['phpType'];
    3687. -
    3688. }
    3689. -
    3690. if (isset($etype['elements'])) {
    3691. -
    3692. $this->elements[$type]['elements'] = $etype['elements'];
    3693. -
    3694. }
    3695. -
    3696. if (isset($etype['extensionBase'])) {
    3697. -
    3698. $this->elements[$type]['extensionBase'] = $etype['extensionBase'];
    3699. -
    3700. }
    3701. -
    3702. } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
    3703. -
    3704. $this->xdebug("in getTypeDef, element $type is an XSD type");
    3705. -
    3706. $this->elements[$type]['phpType'] = 'scalar';
    3707. -
    3708. }
    3709. -
    3710. }
    3711. -
    3712. return $this->elements[$type];
    3713. -
    3714. } elseif(isset($this->attributes[$type])){
    3715. -
    3716. $this->xdebug("in getTypeDef, found attribute $type");
    3717. -
    3718. return $this->attributes[$type];
    3719. -
    3720. } elseif (preg_match('/_ContainedType$/', $type)) {
    3721. -
    3722. $this->xdebug("in getTypeDef, have an untyped element $type");
    3723. -
    3724. $typeDef['typeClass'] = 'simpleType';
    3725. -
    3726. $typeDef['phpType'] = 'scalar';
    3727. -
    3728. $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
    3729. -
    3730. return $typeDef;
    3731. -
    3732. }
    3733. -
    3734. $this->xdebug("in getTypeDef, did not find $type");
    3735. -
    3736. return false;
    3737. -
    3738. }
    3739. -
    3740.  
    3741. -
    3742. /**
    3743. -
    3744. * returns a sample serialization of a given type, or false if no type by the given name
    3745. -
    3746. *
    3747. -
    3748. * @param string $type name of type
    3749. -
    3750. * @return mixed
    3751. -
    3752. * @access public
    3753. -
    3754. * @deprecated
    3755. -
    3756. */
    3757. -
    3758. function serializeTypeDef($type){
    3759. -
    3760. //print "in sTD() for type $type<br>";
    3761. -
    3762. if($typeDef = $this->getTypeDef($type)){
    3763. -
    3764. $str .= '<'.$type;
    3765. -
    3766. if(is_array($typeDef['attrs'])){
    3767. -
    3768. foreach($typeDef['attrs'] as $attName => $data){
    3769. -
    3770. $str .= " $attName=\"{type = ".$data['type']."}\"";
    3771. -
    3772. }
    3773. -
    3774. }
    3775. -
    3776. $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
    3777. -
    3778. if(count($typeDef['elements']) > 0){
    3779. -
    3780. $str .= ">";
    3781. -
    3782. foreach($typeDef['elements'] as $element => $eData){
    3783. -
    3784. $str .= $this->serializeTypeDef($element);
    3785. -
    3786. }
    3787. -
    3788. $str .= "</$type>";
    3789. -
    3790. } elseif($typeDef['typeClass'] == 'element') {
    3791. -
    3792. $str .= "></$type>";
    3793. -
    3794. } else {
    3795. -
    3796. $str .= "/>";
    3797. -
    3798. }
    3799. -
    3800. return $str;
    3801. -
    3802. }
    3803. -
    3804. return false;
    3805. -
    3806. }
    3807. -
    3808.  
    3809. -
    3810. /**
    3811. -
    3812. * returns HTML form elements that allow a user
    3813. -
    3814. * to enter values for creating an instance of the given type.
    3815. -
    3816. *
    3817. -
    3818. * @param string $name name for type instance
    3819. -
    3820. * @param string $type name of type
    3821. -
    3822. * @return string
    3823. -
    3824. * @access public
    3825. -
    3826. * @deprecated
    3827. -
    3828. */
    3829. -
    3830. function typeToForm($name,$type){
    3831. -
    3832. // get typedef
    3833. -
    3834. if($typeDef = $this->getTypeDef($type)){
    3835. -
    3836. // if struct
    3837. -
    3838. if($typeDef['phpType'] == 'struct'){
    3839. -
    3840. $buffer .= '<table>';
    3841. -
    3842. foreach($typeDef['elements'] as $child => $childDef){
    3843. -
    3844. $buffer .= "
    3845. -
    3846. <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
    3847. -
    3848. <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
    3849. -
    3850. }
    3851. -
    3852. $buffer .= '</table>';
    3853. -
    3854. // if array
    3855. -
    3856. } elseif($typeDef['phpType'] == 'array'){
    3857. -
    3858. $buffer .= '<table>';
    3859. -
    3860. for($i=0;$i < 3; $i++){
    3861. -
    3862. $buffer .= "
    3863. -
    3864. <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
    3865. -
    3866. <td><input type='text' name='parameters[".$name."][]'></td></tr>";
    3867. -
    3868. }
    3869. -
    3870. $buffer .= '</table>';
    3871. -
    3872. // if scalar
    3873. -
    3874. } else {
    3875. -
    3876. $buffer .= "<input type='text' name='parameters[$name]'>";
    3877. -
    3878. }
    3879. -
    3880. } else {
    3881. -
    3882. $buffer .= "<input type='text' name='parameters[$name]'>";
    3883. -
    3884. }
    3885. -
    3886. return $buffer;
    3887. -
    3888. }
    3889. -
    3890. -
    3891. /**
    3892. -
    3893. * adds a complex type to the schema
    3894. -
    3895. *
    3896. -
    3897. * example: array
    3898. -
    3899. *
    3900. -
    3901. * addType(
    3902. -
    3903. * 'ArrayOfstring',
    3904. -
    3905. * 'complexType',
    3906. -
    3907. * 'array',
    3908. -
    3909. * '',
    3910. -
    3911. * 'SOAP-ENC:Array',
    3912. -
    3913. * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
    3914. -
    3915. * 'xsd:string'
    3916. -
    3917. * );
    3918. -
    3919. *
    3920. -
    3921. * example: PHP associative array ( SOAP Struct )
    3922. -
    3923. *
    3924. -
    3925. * addType(
    3926. -
    3927. * 'SOAPStruct',
    3928. -
    3929. * 'complexType',
    3930. -
    3931. * 'struct',
    3932. -
    3933. * 'all',
    3934. -
    3935. * array('myVar'=> array('name'=>'myVar','type'=>'string')
    3936. -
    3937. * );
    3938. -
    3939. *
    3940. -
    3941. * @param name
    3942. -
    3943. * @param typeClass (complexType|simpleType|attribute)
    3944. -
    3945. * @param phpType: currently supported are array and struct (php assoc array)
    3946. -
    3947. * @param compositor (all|sequence|choice)
    3948. -
    3949. * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
    3950. -
    3951. * @param elements = array ( name = array(name=>'',type=>'') )
    3952. -
    3953. * @param attrs = array(
    3954. -
    3955. * array(
    3956. -
    3957. * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
    3958. -
    3959. * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
    3960. -
    3961. * )
    3962. -
    3963. * )
    3964. -
    3965. * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
    3966. -
    3967. * @access public
    3968. -
    3969. * @see getTypeDef
    3970. -
    3971. */
    3972. -
    3973. function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
    3974. -
    3975. $this->complexTypes[$name] = array(
    3976. -
    3977. 'name' => $name,
    3978. -
    3979. 'typeClass' => $typeClass,
    3980. -
    3981. 'phpType' => $phpType,
    3982. -
    3983. 'compositor'=> $compositor,
    3984. -
    3985. 'restrictionBase' => $restrictionBase,
    3986. -
    3987. 'elements' => $elements,
    3988. -
    3989. 'attrs' => $attrs,
    3990. -
    3991. 'arrayType' => $arrayType
    3992. -
    3993. );
    3994. -
    3995. -
    3996. $this->xdebug("addComplexType $name:");
    3997. -
    3998. $this->appendDebug($this->varDump($this->complexTypes[$name]));
    3999. -
    4000. }
    4001. -
    4002. -
    4003. /**
    4004. -
    4005. * adds a simple type to the schema
    4006. -
    4007. *
    4008. -
    4009. * @param string $name
    4010. -
    4011. * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
    4012. -
    4013. * @param string $typeClass (should always be simpleType)
    4014. -
    4015. * @param string $phpType (should always be scalar)
    4016. -
    4017. * @param array $enumeration array of values
    4018. -
    4019. * @access public
    4020. -
    4021. * @see nusoap_xmlschema
    4022. -
    4023. * @see getTypeDef
    4024. -
    4025. */
    4026. -
    4027. function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
    4028. -
    4029. $this->simpleTypes[$name] = array(
    4030. -
    4031. 'name' => $name,
    4032. -
    4033. 'typeClass' => $typeClass,
    4034. -
    4035. 'phpType' => $phpType,
    4036. -
    4037. 'type' => $restrictionBase,
    4038. -
    4039. 'enumeration' => $enumeration
    4040. -
    4041. );
    4042. -
    4043. -
    4044. $this->xdebug("addSimpleType $name:");
    4045. -
    4046. $this->appendDebug($this->varDump($this->simpleTypes[$name]));
    4047. -
    4048. }
    4049. -
    4050.  
    4051. -
    4052. /**
    4053. -
    4054. * adds an element to the schema
    4055. -
    4056. *
    4057. -
    4058. * @param array $attrs attributes that must include name and type
    4059. -
    4060. * @see nusoap_xmlschema
    4061. -
    4062. * @access public
    4063. -
    4064. */
    4065. -
    4066. function addElement($attrs) {
    4067. -
    4068. if (! $this->getPrefix($attrs['type'])) {
    4069. -
    4070. $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
    4071. -
    4072. }
    4073. -
    4074. $this->elements[ $attrs['name'] ] = $attrs;
    4075. -
    4076. $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
    4077. -
    4078. -
    4079. $this->xdebug("addElement " . $attrs['name']);
    4080. -
    4081. $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
    4082. -
    4083. }
    4084. -
    4085. }
    4086. -
    4087.  
    4088. -
    4089. /**
    4090. -
    4091. * Backward compatibility
    4092. -
    4093. */
    4094. -
    4095. class XMLSchema extends nusoap_xmlschema {
    4096. -
    4097. }
    4098. -
    4099.  
    4100. -
    4101. ?><?php
    4102. -
    4103.  
    4104. -
    4105.  
    4106. -
    4107.  
    4108. -
    4109. /**
    4110. -
    4111. * For creating serializable abstractions of native PHP types. This class
    4112. -
    4113. * allows element name/namespace, XSD type, and XML attributes to be
    4114. -
    4115. * associated with a value. This is extremely useful when WSDL is not
    4116. -
    4117. * used, but is also useful when WSDL is used with polymorphic types, including
    4118. -
    4119. * xsd:anyType and user-defined types.
    4120. -
    4121. *
    4122. -
    4123. * @author Dietrich Ayala <dietrich@ganx4.com>
    4124. -
    4125. * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    4126. -
    4127. * @access public
    4128. -
    4129. */
    4130. -
    4131. class soapval extends nusoap_base {
    4132. -
    4133. /**
    4134. -
    4135. * The XML element name
    4136. -
    4137. *
    4138. -
    4139. * @var string
    4140. -
    4141. * @access private
    4142. -
    4143. */
    4144. -
    4145. var $name;
    4146. -
    4147. /**
    4148. -
    4149. * The XML type name (string or false)
    4150. -
    4151. *
    4152. -
    4153. * @var mixed
    4154. -
    4155. * @access private
    4156. -
    4157. */
    4158. -
    4159. var $type;
    4160. -
    4161. /**
    4162. -
    4163. * The PHP value
    4164. -
    4165. *
    4166. -
    4167. * @var mixed
    4168. -
    4169. * @access private
    4170. -
    4171. */
    4172. -
    4173. var $value;
    4174. -
    4175. /**
    4176. -
    4177. * The XML element namespace (string or false)
    4178. -
    4179. *
    4180. -
    4181. * @var mixed
    4182. -
    4183. * @access private
    4184. -
    4185. */
    4186. -
    4187. var $element_ns;
    4188. -
    4189. /**
    4190. -
    4191. * The XML type namespace (string or false)
    4192. -
    4193. *
    4194. -
    4195. * @var mixed
    4196. -
    4197. * @access private
    4198. -
    4199. */
    4200. -
    4201. var $type_ns;
    4202. -
    4203. /**
    4204. -
    4205. * The XML element attributes (array or false)
    4206. -
    4207. *
    4208. -
    4209. * @var mixed
    4210. -
    4211. * @access private
    4212. -
    4213. */
    4214. -
    4215. var $attributes;
    4216. -
    4217.  
    4218. -
    4219. /**
    4220. -
    4221. * constructor
    4222. -
    4223. *
    4224. -
    4225. * @param string $name optional name
    4226. -
    4227. * @param mixed $type optional type name
    4228. -
    4229. * @param mixed $value optional value
    4230. -
    4231. * @param mixed $element_ns optional namespace of value
    4232. -
    4233. * @param mixed $type_ns optional namespace of type
    4234. -
    4235. * @param mixed $attributes associative array of attributes to add to element serialization
    4236. -
    4237. * @access public
    4238. -
    4239. */
    4240. -
    4241. function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
    4242. -
    4243. parent::nusoap_base();
    4244. -
    4245. $this->name = $name;
    4246. -
    4247. $this->type = $type;
    4248. -
    4249. $this->value = $value;
    4250. -
    4251. $this->element_ns = $element_ns;
    4252. -
    4253. $this->type_ns = $type_ns;
    4254. -
    4255. $this->attributes = $attributes;
    4256. -
    4257. }
    4258. -
    4259.  
    4260. -
    4261. /**
    4262. -
    4263. * return serialized value
    4264. -
    4265. *
    4266. -
    4267. * @param string $use The WSDL use value (encoded|literal)
    4268. -
    4269. * @return string XML data
    4270. -
    4271. * @access public
    4272. -
    4273. */
    4274. -
    4275. function serialize($use='encoded') {
    4276. -
    4277. return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
    4278. -
    4279. }
    4280. -
    4281.  
    4282. -
    4283. /**
    4284. -
    4285. * decodes a soapval object into a PHP native type
    4286. -
    4287. *
    4288. -
    4289. * @return mixed
    4290. -
    4291. * @access public
    4292. -
    4293. */
    4294. -
    4295. function decode(){
    4296. -
    4297. return $this->value;
    4298. -
    4299. }
    4300. -
    4301. }
    4302. -
    4303.  
    4304. -
    4305.  
    4306. -
    4307.  
    4308. -
    4309. ?><?php
    4310. -
    4311.  
    4312. -
    4313.  
    4314. -
    4315.  
    4316. -
    4317. /**
    4318. -
    4319. * transport class for sending/receiving data via HTTP and HTTPS
    4320. -
    4321. * NOTE: PHP must be compiled with the CURL extension for HTTPS support
    4322. -
    4323. *
    4324. -
    4325. * @author Dietrich Ayala <dietrich@ganx4.com>
    4326. -
    4327. * @author Scott Nichol <snichol@users.sourceforge.net>
    4328. -
    4329. * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    4330. -
    4331. * @access public
    4332. -
    4333. */
    4334. -
    4335. class soap_transport_http extends nusoap_base {
    4336. -
    4337.  
    4338. -
    4339. var $url = '';
    4340. -
    4341. var $uri = '';
    4342. -
    4343. var $digest_uri = '';
    4344. -
    4345. var $scheme = '';
    4346. -
    4347. var $host = '';
    4348. -
    4349. var $port = '';
    4350. -
    4351. var $path = '';
    4352. -
    4353. var $request_method = 'POST';
    4354. -
    4355. var $protocol_version = '1.0';
    4356. -
    4357. var $encoding = '';
    4358. -
    4359. var $outgoing_headers = array();
    4360. -
    4361. var $incoming_headers = array();
    4362. -
    4363. var $incoming_cookies = array();
    4364. -
    4365. var $outgoing_payload = '';
    4366. -
    4367. var $incoming_payload = '';
    4368. -
    4369. var $response_status_line; // HTTP response status line
    4370. -
    4371. -
    4372. var $useSOAPAction = true;
    4373. -
    4374. var $persistentConnection = false;
    4375. -
    4376. var $ch = false; // cURL handle
    4377. -
    4378. -
    4379. var $ch_options = array(); // cURL custom options
    4380. -
    4381. -
    4382. var $use_curl = false; // force cURL use
    4383. -
    4384. -
    4385. var $proxy = null; // proxy information (associative array)
    4386. -
    4387. -
    4388. var $username = '';
    4389. -
    4390. var $password = '';
    4391. -
    4392. var $authtype = '';
    4393. -
    4394. var $digestRequest = array();
    4395. -
    4396. var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
    4397. -
    4398. // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
    4399. -
    4400. // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
    4401. -
    4402. // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
    4403. -
    4404. // passphrase: SSL key password/passphrase
    4405. -
    4406. // certpassword: SSL certificate password
    4407. -
    4408. // verifypeer: default is 1
    4409. -
    4410. // verifyhost: default is 1
    4411. -
    4412.  
    4413. -
    4414. -
    4415.  
    4416. -
    4417. /**
    4418. -
    4419. * constructor
    4420. -
    4421. *
    4422. -
    4423. * @param string $url The URL to which to connect
    4424. -
    4425. * @param array $curl_options User-specified cURL options
    4426. -
    4427. * @param boolean $use_curl Whether to try to force cURL use
    4428. -
    4429. * @access public
    4430. -
    4431. */
    4432. -
    4433. function soap_transport_http($url, $curl_options = NULL, $use_curl = false){
    4434. -
    4435. parent::nusoap_base();
    4436. -
    4437. $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
    4438. -
    4439. $this->appendDebug($this->varDump($curl_options));
    4440. -
    4441. $this->setURL($url);
    4442. -
    4443. if (is_array($curl_options)) {
    4444. -
    4445. $this->ch_options = $curl_options;
    4446. -
    4447. }
    4448. -
    4449. $this->use_curl = $use_curl;
    4450. -
    4451. preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
    4452. -
    4453. $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
    4454. -
    4455. }
    4456. -
    4457.  
    4458. -
    4459. /**
    4460. -
    4461. * sets a cURL option
    4462. -
    4463. *
    4464. -
    4465. * @param mixed $option The cURL option (always integer?)
    4466. -
    4467. * @param mixed $value The cURL option value
    4468. -
    4469. * @access private
    4470. -
    4471. */
    4472. -
    4473. function setCurlOption($option, $value) {
    4474. -
    4475. $this->debug("setCurlOption option=$option, value=");
    4476. -
    4477. $this->appendDebug($this->varDump($value));
    4478. -
    4479. curl_setopt($this->ch, $option, $value);
    4480. -
    4481. }
    4482. -
    4483.  
    4484. -
    4485. /**
    4486. -
    4487. * sets an HTTP header
    4488. -
    4489. *
    4490. -
    4491. * @param string $name The name of the header
    4492. -
    4493. * @param string $value The value of the header
    4494. -
    4495. * @access private
    4496. -
    4497. */
    4498. -
    4499. function setHeader($name, $value) {
    4500. -
    4501. $this->outgoing_headers[$name] = $value;
    4502. -
    4503. $this->debug("set header $name: $value");
    4504. -
    4505. }
    4506. -
    4507.  
    4508. -
    4509. /**
    4510. -
    4511. * unsets an HTTP header
    4512. -
    4513. *
    4514. -
    4515. * @param string $name The name of the header
    4516. -
    4517. * @access private
    4518. -
    4519. */
    4520. -
    4521. function unsetHeader($name) {
    4522. -
    4523. if (isset($this->outgoing_headers[$name])) {
    4524. -
    4525. $this->debug("unset header $name");
    4526. -
    4527. unset($this->outgoing_headers[$name]);
    4528. -
    4529. }
    4530. -
    4531. }
    4532. -
    4533.  
    4534. -
    4535. /**
    4536. -
    4537. * sets the URL to which to connect
    4538. -
    4539. *
    4540. -
    4541. * @param string $url The URL to which to connect
    4542. -
    4543. * @access private
    4544. -
    4545. */
    4546. -
    4547. function setURL($url) {
    4548. -
    4549. $this->url = $url;
    4550. -
    4551.  
    4552. -
    4553. $u = parse_url($url);
    4554. -
    4555. foreach($u as $k => $v){
    4556. -
    4557. $this->debug("parsed URL $k = $v");
    4558. -
    4559. $this->$k = $v;
    4560. -
    4561. }
    4562. -
    4563. -
    4564. // add any GET params to path
    4565. -
    4566. if(isset($u['query']) && $u['query'] != ''){
    4567. -
    4568. $this->path .= '?' . $u['query'];
    4569. -
    4570. }
    4571. -
    4572. -
    4573. // set default port
    4574. -
    4575. if(!isset($u['port'])){
    4576. -
    4577. if($u['scheme'] == 'https'){
    4578. -
    4579. $this->port = 443;
    4580. -
    4581. } else {
    4582. -
    4583. $this->port = 80;
    4584. -
    4585. }
    4586. -
    4587. }
    4588. -
    4589. -
    4590. $this->uri = $this->path;
    4591. -
    4592. $this->digest_uri = $this->uri;
    4593. -
    4594. -
    4595. // build headers
    4596. -
    4597. if (!isset($u['port'])) {
    4598. -
    4599. $this->setHeader('Host', $this->host);
    4600. -
    4601. } else {
    4602. -
    4603. $this->setHeader('Host', $this->host.':'.$this->port);
    4604. -
    4605. }
    4606. -
    4607.  
    4608. -
    4609. if (isset($u['user']) && $u['user'] != '') {
    4610. -
    4611. $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
    4612. -
    4613. }
    4614. -
    4615. }
    4616. -
    4617.  
    4618. -
    4619. /**
    4620. -
    4621. * gets the I/O method to use
    4622. -
    4623. *
    4624. -
    4625. * @return string I/O method to use (socket|curl|unknown)
    4626. -
    4627. * @access private
    4628. -
    4629. */
    4630. -
    4631. function io_method() {
    4632. -
    4633. if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
    4634. -
    4635. return 'curl';
    4636. -
    4637. if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
    4638. -
    4639. return 'socket';
    4640. -
    4641. return 'unknown';
    4642. -
    4643. }
    4644. -
    4645.  
    4646. -
    4647. /**
    4648. -
    4649. * establish an HTTP connection
    4650. -
    4651. *
    4652. -
    4653. * @param integer $timeout set connection timeout in seconds
    4654. -
    4655. * @param integer $response_timeout set response timeout in seconds
    4656. -
    4657. * @return boolean true if connected, false if not
    4658. -
    4659. * @access private
    4660. -
    4661. */
    4662. -
    4663. function connect($connection_timeout=0,$response_timeout=30){
    4664. -
    4665. // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
    4666. -
    4667. // "regular" socket.
    4668. -
    4669. // TODO: disabled for now because OpenSSL must be *compiled* in (not just
    4670. -
    4671. // loaded), and until PHP5 stream_get_wrappers is not available.
    4672. -
    4673. // if ($this->scheme == 'https') {
    4674. -
    4675. // if (version_compare(phpversion(), '4.3.0') >= 0) {
    4676. -
    4677. // if (extension_loaded('openssl')) {
    4678. -
    4679. // $this->scheme = 'ssl';
    4680. -
    4681. // $this->debug('Using SSL over OpenSSL');
    4682. -
    4683. // }
    4684. -
    4685. // }
    4686. -
    4687. // }
    4688. -
    4689. $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
    4690. -
    4691. if ($this->io_method() == 'socket') {
    4692. -
    4693. if (!is_array($this->proxy)) {
    4694. -
    4695. $host = $this->host;
    4696. -
    4697. $port = $this->port;
    4698. -
    4699. } else {
    4700. -
    4701. $host = $this->proxy['host'];
    4702. -
    4703. $port = $this->proxy['port'];
    4704. -
    4705. }
    4706. -
    4707.  
    4708. -
    4709. // use persistent connection
    4710. -
    4711. if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
    4712. -
    4713. if (!feof($this->fp)) {
    4714. -
    4715. $this->debug('Re-use persistent connection');
    4716. -
    4717. return true;
    4718. -
    4719. }
    4720. -
    4721. fclose($this->fp);
    4722. -
    4723. $this->debug('Closed persistent connection at EOF');
    4724. -
    4725. }
    4726. -
    4727.  
    4728. -
    4729. // munge host if using OpenSSL
    4730. -
    4731. if ($this->scheme == 'ssl') {
    4732. -
    4733. $host = 'ssl://' . $host;
    4734. -
    4735. }
    4736. -
    4737. $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
    4738. -
    4739.  
    4740. -
    4741. // open socket
    4742. -
    4743. if($connection_timeout > 0){
    4744. -
    4745. $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
    4746. -
    4747. } else {
    4748. -
    4749. $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
    4750. -
    4751. }
    4752. -
    4753. -
    4754. // test pointer
    4755. -
    4756. if(!$this->fp) {
    4757. -
    4758. $msg = 'Couldn\'t open socket connection to server ' . $this->url;
    4759. -
    4760. if ($this->errno) {
    4761. -
    4762. $msg .= ', Error ('.$this->errno.'): '.$this->error_str;
    4763. -
    4764. } else {
    4765. -
    4766. $msg .= ' prior to connect(). This is often a problem looking up the host name.';
    4767. -
    4768. }
    4769. -
    4770. $this->debug($msg);
    4771. -
    4772. $this->setError($msg);
    4773. -
    4774. return false;
    4775. -
    4776. }
    4777. -
    4778. -
    4779. // set response timeout
    4780. -
    4781. $this->debug('set response timeout to ' . $response_timeout);
    4782. -
    4783. socket_set_timeout( $this->fp, $response_timeout);
    4784. -
    4785.  
    4786. -
    4787. $this->debug('socket connected');
    4788. -
    4789. return true;
    4790. -
    4791. } else if ($this->io_method() == 'curl') {
    4792. -
    4793. if (!extension_loaded('curl')) {
    4794. -
    4795. // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
    4796. -
    4797. $this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to include cURL or change php.ini to load the PHP cURL extension.');
    4798. -
    4799. return false;
    4800. -
    4801. }
    4802. -
    4803. // Avoid warnings when PHP does not have these options
    4804. -
    4805. if (defined('CURLOPT_CONNECTIONTIMEOUT'))
    4806. -
    4807. $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
    4808. -
    4809. else
    4810. -
    4811. $CURLOPT_CONNECTIONTIMEOUT = 78;
    4812. -
    4813. if (defined('CURLOPT_HTTPAUTH'))
    4814. -
    4815. $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
    4816. -
    4817. else
    4818. -
    4819. $CURLOPT_HTTPAUTH = 107;
    4820. -
    4821. if (defined('CURLOPT_PROXYAUTH'))
    4822. -
    4823. $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
    4824. -
    4825. else
    4826. -
    4827. $CURLOPT_PROXYAUTH = 111;
    4828. -
    4829. if (defined('CURLAUTH_BASIC'))
    4830. -
    4831. $CURLAUTH_BASIC = CURLAUTH_BASIC;
    4832. -
    4833. else
    4834. -
    4835. $CURLAUTH_BASIC = 1;
    4836. -
    4837. if (defined('CURLAUTH_DIGEST'))
    4838. -
    4839. $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
    4840. -
    4841. else
    4842. -
    4843. $CURLAUTH_DIGEST = 2;
    4844. -
    4845. if (defined('CURLAUTH_NTLM'))
    4846. -
    4847. $CURLAUTH_NTLM = CURLAUTH_NTLM;
    4848. -
    4849. else
    4850. -
    4851. $CURLAUTH_NTLM = 8;
    4852. -
    4853.  
    4854. -
    4855. $this->debug('connect using cURL');
    4856. -
    4857. // init CURL
    4858. -
    4859. $this->ch = curl_init();
    4860. -
    4861. // set url
    4862. -
    4863. $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
    4864. -
    4865. // add path
    4866. -
    4867. $hostURL .= $this->path;
    4868. -
    4869. $this->setCurlOption(CURLOPT_URL, $hostURL);
    4870. -
    4871. // follow location headers (re-directs)
    4872. -
    4873. if (ini_get('safe_mode') || ini_get('open_basedir')) {
    4874. -
    4875. $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
    4876. -
    4877. $this->debug('safe_mode = ');
    4878. -
    4879. $this->appendDebug($this->varDump(ini_get('safe_mode')));
    4880. -
    4881. $this->debug('open_basedir = ');
    4882. -
    4883. $this->appendDebug($this->varDump(ini_get('open_basedir')));
    4884. -
    4885. } else {
    4886. -
    4887. $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
    4888. -
    4889. }
    4890. -
    4891. // ask for headers in the response output
    4892. -
    4893. $this->setCurlOption(CURLOPT_HEADER, 1);
    4894. -
    4895. // ask for the response output as the return value
    4896. -
    4897. $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
    4898. -
    4899. // encode
    4900. -
    4901. // We manage this ourselves through headers and encoding
    4902. -
    4903. // if(function_exists('gzuncompress')){
    4904. -
    4905. // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
    4906. -
    4907. // }
    4908. -
    4909. // persistent connection
    4910. -
    4911. if ($this->persistentConnection) {
    4912. -
    4913. // I believe the following comment is now bogus, having applied to
    4914. -
    4915. // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
    4916. -
    4917. // The way we send data, we cannot use persistent connections, since
    4918. -
    4919. // there will be some "junk" at the end of our request.
    4920. -
    4921. //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
    4922. -
    4923. $this->persistentConnection = false;
    4924. -
    4925. $this->setHeader('Connection', 'close');
    4926. -
    4927. }
    4928. -
    4929. // set timeouts
    4930. -
    4931. if ($connection_timeout != 0) {
    4932. -
    4933. $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
    4934. -
    4935. }
    4936. -
    4937. if ($response_timeout != 0) {
    4938. -
    4939. $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
    4940. -
    4941. }
    4942. -
    4943.  
    4944. -
    4945. if ($this->scheme == 'https') {
    4946. -
    4947. $this->debug('set cURL SSL verify options');
    4948. -
    4949. // recent versions of cURL turn on peer/host checking by default,
    4950. -
    4951. // while PHP binaries are not compiled with a default location for the
    4952. -
    4953. // CA cert bundle, so disable peer/host checking.
    4954. -
    4955. //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
    4956. -
    4957. $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
    4958. -
    4959. $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
    4960. -
    4961. -
    4962. // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
    4963. -
    4964. if ($this->authtype == 'certificate') {
    4965. -
    4966. $this->debug('set cURL certificate options');
    4967. -
    4968. if (isset($this->certRequest['cainfofile'])) {
    4969. -
    4970. $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
    4971. -
    4972. }
    4973. -
    4974. if (isset($this->certRequest['verifypeer'])) {
    4975. -
    4976. $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
    4977. -
    4978. } else {
    4979. -
    4980. $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
    4981. -
    4982. }
    4983. -
    4984. if (isset($this->certRequest['verifyhost'])) {
    4985. -
    4986. $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
    4987. -
    4988. } else {
    4989. -
    4990. $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
    4991. -
    4992. }
    4993. -
    4994. if (isset($this->certRequest['sslcertfile'])) {
    4995. -
    4996. $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
    4997. -
    4998. }
    4999. -
    5000. if (isset($this->certRequest['sslkeyfile'])) {
    5001. -
    5002. $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
    5003. -
    5004. }
    5005. -
    5006. if (isset($this->certRequest['passphrase'])) {
    5007. -
    5008. $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
    5009. -
    5010. }
    5011. -
    5012. if (isset($this->certRequest['certpassword'])) {
    5013. -
    5014. $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
    5015. -
    5016. }
    5017. -
    5018. }
    5019. -
    5020. }
    5021. -
    5022. if ($this->authtype && ($this->authtype != 'certificate')) {
    5023. -
    5024. if ($this->username) {
    5025. -
    5026. $this->debug('set cURL username/password');
    5027. -
    5028. $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
    5029. -
    5030. }
    5031. -
    5032. if ($this->authtype == 'basic') {
    5033. -
    5034. $this->debug('set cURL for Basic authentication');
    5035. -
    5036. $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
    5037. -
    5038. }
    5039. -
    5040. if ($this->authtype == 'digest') {
    5041. -
    5042. $this->debug('set cURL for digest authentication');
    5043. -
    5044. $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
    5045. -
    5046. }
    5047. -
    5048. if ($this->authtype == 'ntlm') {
    5049. -
    5050. $this->debug('set cURL for NTLM authentication');
    5051. -
    5052. $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
    5053. -
    5054. }
    5055. -
    5056. }
    5057. -
    5058. if (is_array($this->proxy)) {
    5059. -
    5060. $this->debug('set cURL proxy options');
    5061. -
    5062. if ($this->proxy['port'] != '') {
    5063. -
    5064. $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
    5065. -
    5066. } else {
    5067. -
    5068. $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
    5069. -
    5070. }
    5071. -
    5072. if ($this->proxy['username'] || $this->proxy['password']) {
    5073. -
    5074. $this->debug('set cURL proxy authentication options');
    5075. -
    5076. $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
    5077. -
    5078. if ($this->proxy['authtype'] == 'basic') {
    5079. -
    5080. $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
    5081. -
    5082. }
    5083. -
    5084. if ($this->proxy['authtype'] == 'ntlm') {
    5085. -
    5086. $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
    5087. -
    5088. }
    5089. -
    5090. }
    5091. -
    5092. }
    5093. -
    5094. $this->debug('cURL connection set up');
    5095. -
    5096. return true;
    5097. -
    5098. } else {
    5099. -
    5100. $this->setError('Unknown scheme ' . $this->scheme);
    5101. -
    5102. $this->debug('Unknown scheme ' . $this->scheme);
    5103. -
    5104. return false;
    5105. -
    5106. }
    5107. -
    5108. }
    5109. -
    5110.  
    5111. -
    5112. /**
    5113. -
    5114. * sends the SOAP request and gets the SOAP response via HTTP[S]
    5115. -
    5116. *
    5117. -
    5118. * @param string $data message data
    5119. -
    5120. * @param integer $timeout set connection timeout in seconds
    5121. -
    5122. * @param integer $response_timeout set response timeout in seconds
    5123. -
    5124. * @param array $cookies cookies to send
    5125. -
    5126. * @return string data
    5127. -
    5128. * @access public
    5129. -
    5130. */
    5131. -
    5132. function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
    5133. -
    5134. -
    5135. $this->debug('entered send() with data of length: '.strlen($data));
    5136. -
    5137.  
    5138. -
    5139. $this->tryagain = true;
    5140. -
    5141. $tries = 0;
    5142. -
    5143. while ($this->tryagain) {
    5144. -
    5145. $this->tryagain = false;
    5146. -
    5147. if ($tries++ < 2) {
    5148. -
    5149. // make connnection
    5150. -
    5151. if (!$this->connect($timeout, $response_timeout)){
    5152. -
    5153. return false;
    5154. -
    5155. }
    5156. -
    5157. -
    5158. // send request
    5159. -
    5160. if (!$this->sendRequest($data, $cookies)){
    5161. -
    5162. return false;
    5163. -
    5164. }
    5165. -
    5166. -
    5167. // get response
    5168. -
    5169. $respdata = $this->getResponse();
    5170. -
    5171. } else {
    5172. -
    5173. $this->setError("Too many tries to get an OK response ($this->response_status_line)");
    5174. -
    5175. }
    5176. -
    5177. }
    5178. -
    5179. $this->debug('end of send()');
    5180. -
    5181. return $respdata;
    5182. -
    5183. }
    5184. -
    5185.  
    5186. -
    5187.  
    5188. -
    5189. /**
    5190. -
    5191. * sends the SOAP request and gets the SOAP response via HTTPS using CURL
    5192. -
    5193. *
    5194. -
    5195. * @param string $data message data
    5196. -
    5197. * @param integer $timeout set connection timeout in seconds
    5198. -
    5199. * @param integer $response_timeout set response timeout in seconds
    5200. -
    5201. * @param array $cookies cookies to send
    5202. -
    5203. * @return string data
    5204. -
    5205. * @access public
    5206. -
    5207. * @deprecated
    5208. -
    5209. */
    5210. -
    5211. function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
    5212. -
    5213. return $this->send($data, $timeout, $response_timeout, $cookies);
    5214. -
    5215. }
    5216. -
    5217. -
    5218. /**
    5219. -
    5220. * if authenticating, set user credentials here
    5221. -
    5222. *
    5223. -
    5224. * @param string $username
    5225. -
    5226. * @param string $password
    5227. -
    5228. * @param string $authtype (basic|digest|certificate|ntlm)
    5229. -
    5230. * @param array $digestRequest (keys must be nonce, nc, realm, qop)
    5231. -
    5232. * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
    5233. -
    5234. * @access public
    5235. -
    5236. */
    5237. -
    5238. function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
    5239. -
    5240. $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
    5241. -
    5242. $this->appendDebug($this->varDump($digestRequest));
    5243. -
    5244. $this->debug("certRequest=");
    5245. -
    5246. $this->appendDebug($this->varDump($certRequest));
    5247. -
    5248. // cf. RFC 2617
    5249. -
    5250. if ($authtype == 'basic') {
    5251. -
    5252. $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
    5253. -
    5254. } elseif ($authtype == 'digest') {
    5255. -
    5256. if (isset($digestRequest['nonce'])) {
    5257. -
    5258. $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
    5259. -
    5260. -
    5261. // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
    5262. -
    5263. -
    5264. // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
    5265. -
    5266. $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
    5267. -
    5268. -
    5269. // H(A1) = MD5(A1)
    5270. -
    5271. $HA1 = md5($A1);
    5272. -
    5273. -
    5274. // A2 = Method ":" digest-uri-value
    5275. -
    5276. $A2 = $this->request_method . ':' . $this->digest_uri;
    5277. -
    5278. -
    5279. // H(A2)
    5280. -
    5281. $HA2 = md5($A2);
    5282. -
    5283. -
    5284. // KD(secret, data) = H(concat(secret, ":", data))
    5285. -
    5286. // if qop == auth:
    5287. -
    5288. // request-digest = <"> < KD ( H(A1), unq(nonce-value)
    5289. -
    5290. // ":" nc-value
    5291. -
    5292. // ":" unq(cnonce-value)
    5293. -
    5294. // ":" unq(qop-value)
    5295. -
    5296. // ":" H(A2)
    5297. -
    5298. // ) <">
    5299. -
    5300. // if qop is missing,
    5301. -
    5302. // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
    5303. -
    5304. -
    5305. $unhashedDigest = '';
    5306. -
    5307. $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
    5308. -
    5309. $cnonce = $nonce;
    5310. -
    5311. if ($digestRequest['qop'] != '') {
    5312. -
    5313. $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
    5314. -
    5315. } else {
    5316. -
    5317. $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
    5318. -
    5319. }
    5320. -
    5321. -
    5322. $hashedDigest = md5($unhashedDigest);
    5323. -
    5324. -
    5325. $opaque = '';
    5326. -
    5327. if (isset($digestRequest['opaque'])) {
    5328. -
    5329. $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
    5330. -
    5331. }
    5332. -
    5333.  
    5334. -
    5335. $this->setHeader('Authorization', 'Digest username="' . $username . '", realm="' . $digestRequest['realm'] . '", nonce="' . $nonce . '", uri="' . $this->digest_uri . $opaque . '", cnonce="' . $cnonce . '", nc=' . sprintf("%08x", $digestRequest['nc']) . ', qop="' . $digestRequest['qop'] . '", response="' . $hashedDigest . '"');
    5336. -
    5337. }
    5338. -
    5339. } elseif ($authtype == 'certificate') {
    5340. -
    5341. $this->certRequest = $certRequest;
    5342. -
    5343. $this->debug('Authorization header not set for certificate');
    5344. -
    5345. } elseif ($authtype == 'ntlm') {
    5346. -
    5347. // do nothing
    5348. -
    5349. $this->debug('Authorization header not set for ntlm');
    5350. -
    5351. }
    5352. -
    5353. $this->username = $username;
    5354. -
    5355. $this->password = $password;
    5356. -
    5357. $this->authtype = $authtype;
    5358. -
    5359. $this->digestRequest = $digestRequest;
    5360. -
    5361. }
    5362. -
    5363. -
    5364. /**
    5365. -
    5366. * set the soapaction value
    5367. -
    5368. *
    5369. -
    5370. * @param string $soapaction
    5371. -
    5372. * @access public
    5373. -
    5374. */
    5375. -
    5376. function setSOAPAction($soapaction) {
    5377. -
    5378. $this->setHeader('SOAPAction', '"' . $soapaction . '"');
    5379. -
    5380. }
    5381. -
    5382. -
    5383. /**
    5384. -
    5385. * use http encoding
    5386. -
    5387. *
    5388. -
    5389. * @param string $enc encoding style. supported values: gzip, deflate, or both
    5390. -
    5391. * @access public
    5392. -
    5393. */
    5394. -
    5395. function setEncoding($enc='gzip, deflate') {
    5396. -
    5397. if (function_exists('gzdeflate')) {
    5398. -
    5399. $this->protocol_version = '1.1';
    5400. -
    5401. $this->setHeader('Accept-Encoding', $enc);
    5402. -
    5403. if (!isset($this->outgoing_headers['Connection'])) {
    5404. -
    5405. $this->setHeader('Connection', 'close');
    5406. -
    5407. $this->persistentConnection = false;
    5408. -
    5409. }
    5410. -
    5411. // deprecated as of PHP 5.3.0
    5412. -
    5413. //set_magic_quotes_runtime(0);
    5414. -
    5415. $this->encoding = $enc;
    5416. -
    5417. }
    5418. -
    5419. }
    5420. -
    5421. -
    5422. /**
    5423. -
    5424. * set proxy info here
    5425. -
    5426. *
    5427. -
    5428. * @param string $proxyhost use an empty string to remove proxy
    5429. -
    5430. * @param string $proxyport
    5431. -
    5432. * @param string $proxyusername
    5433. -
    5434. * @param string $proxypassword
    5435. -
    5436. * @param string $proxyauthtype (basic|ntlm)
    5437. -
    5438. * @access public
    5439. -
    5440. */
    5441. -
    5442. function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
    5443. -
    5444. if ($proxyhost) {
    5445. -
    5446. $this->proxy = array(
    5447. -
    5448. 'host' => $proxyhost,
    5449. -
    5450. 'port' => $proxyport,
    5451. -
    5452. 'username' => $proxyusername,
    5453. -
    5454. 'password' => $proxypassword,
    5455. -
    5456. 'authtype' => $proxyauthtype
    5457. -
    5458. );
    5459. -
    5460. if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
    5461. -
    5462. $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
    5463. -
    5464. }
    5465. -
    5466. } else {
    5467. -
    5468. $this->debug('remove proxy');
    5469. -
    5470. $proxy = null;
    5471. -
    5472. unsetHeader('Proxy-Authorization');
    5473. -
    5474. }
    5475. -
    5476. }
    5477. -
    5478. -
    5479.  
    5480. -
    5481. /**
    5482. -
    5483. * Test if the given string starts with a header that is to be skipped.
    5484. -
    5485. * Skippable headers result from chunked transfer and proxy requests.
    5486. -
    5487. *
    5488. -
    5489. * @param string $data The string to check.
    5490. -
    5491. * @returns boolean Whether a skippable header was found.
    5492. -
    5493. * @access private
    5494. -
    5495. */
    5496. -
    5497. function isSkippableCurlHeader(&$data) {
    5498. -
    5499. $skipHeaders = array( 'HTTP/1.1 100',
    5500. -
    5501. 'HTTP/1.0 301',
    5502. -
    5503. 'HTTP/1.1 301',
    5504. -
    5505. 'HTTP/1.0 302',
    5506. -
    5507. 'HTTP/1.1 302',
    5508. -
    5509. 'HTTP/1.0 401',
    5510. -
    5511. 'HTTP/1.1 401',
    5512. -
    5513. 'HTTP/1.0 200 Connection established');
    5514. -
    5515. foreach ($skipHeaders as $hd) {
    5516. -
    5517. $prefix = substr($data, 0, strlen($hd));
    5518. -
    5519. if ($prefix == $hd) return true;
    5520. -
    5521. }
    5522. -
    5523.  
    5524. -
    5525. return false;
    5526. -
    5527. }
    5528. -
    5529.  
    5530. -
    5531. /**
    5532. -
    5533. * decode a string that is encoded w/ "chunked' transfer encoding
    5534. -
    5535. * as defined in RFC2068 19.4.6
    5536. -
    5537. *
    5538. -
    5539. * @param string $buffer
    5540. -
    5541. * @param string $lb
    5542. -
    5543. * @returns string
    5544. -
    5545. * @access public
    5546. -
    5547. * @deprecated
    5548. -
    5549. */
    5550. -
    5551. function decodeChunked($buffer, $lb){
    5552. -
    5553. // length := 0
    5554. -
    5555. $length = 0;
    5556. -
    5557. $new = '';
    5558. -
    5559. -
    5560. // read chunk-size, chunk-extension (if any) and CRLF
    5561. -
    5562. // get the position of the linebreak
    5563. -
    5564. $chunkend = strpos($buffer, $lb);
    5565. -
    5566. if ($chunkend == FALSE) {
    5567. -
    5568. $this->debug('no linebreak found in decodeChunked');
    5569. -
    5570. return $new;
    5571. -
    5572. }
    5573. -
    5574. $temp = substr($buffer,0,$chunkend);
    5575. -
    5576. $chunk_size = hexdec( trim($temp) );
    5577. -
    5578. $chunkstart = $chunkend + strlen($lb);
    5579. -
    5580. // while (chunk-size > 0) {
    5581. -
    5582. while ($chunk_size > 0) {
    5583. -
    5584. $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
    5585. -
    5586. $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
    5587. -
    5588. -
    5589. // Just in case we got a broken connection
    5590. -
    5591. if ($chunkend == FALSE) {
    5592. -
    5593. $chunk = substr($buffer,$chunkstart);
    5594. -
    5595. // append chunk-data to entity-body
    5596. -
    5597. $new .= $chunk;
    5598. -
    5599. $length += strlen($chunk);
    5600. -
    5601. break;
    5602. -
    5603. }
    5604. -
    5605. -
    5606. // read chunk-data and CRLF
    5607. -
    5608. $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
    5609. -
    5610. // append chunk-data to entity-body
    5611. -
    5612. $new .= $chunk;
    5613. -
    5614. // length := length + chunk-size
    5615. -
    5616. $length += strlen($chunk);
    5617. -
    5618. // read chunk-size and CRLF
    5619. -
    5620. $chunkstart = $chunkend + strlen($lb);
    5621. -
    5622. -
    5623. $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
    5624. -
    5625. if ($chunkend == FALSE) {
    5626. -
    5627. break; //Just in case we got a broken connection
    5628. -
    5629. }
    5630. -
    5631. $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
    5632. -
    5633. $chunk_size = hexdec( trim($temp) );
    5634. -
    5635. $chunkstart = $chunkend;
    5636. -
    5637. }
    5638. -
    5639. return $new;
    5640. -
    5641. }
    5642. -
    5643. -
    5644. /**
    5645. -
    5646. * Writes the payload, including HTTP headers, to $this->outgoing_payload.
    5647. -
    5648. *
    5649. -
    5650. * @param string $data HTTP body
    5651. -
    5652. * @param string $cookie_str data for HTTP Cookie header
    5653. -
    5654. * @return void
    5655. -
    5656. * @access private
    5657. -
    5658. */
    5659. -
    5660. function buildPayload($data, $cookie_str = '') {
    5661. -
    5662. // Note: for cURL connections, $this->outgoing_payload is ignored,
    5663. -
    5664. // as is the Content-Length header, but these are still created as
    5665. -
    5666. // debugging guides.
    5667. -
    5668.  
    5669. -
    5670. // add content-length header
    5671. -
    5672. if ($this->request_method != 'GET') {
    5673. -
    5674. $this->setHeader('Content-Length', strlen($data));
    5675. -
    5676. }
    5677. -
    5678.  
    5679. -
    5680. // start building outgoing payload:
    5681. -
    5682. if ($this->proxy) {
    5683. -
    5684. $uri = $this->url;
    5685. -
    5686. } else {
    5687. -
    5688. $uri = $this->uri;
    5689. -
    5690. }
    5691. -
    5692. $req = "$this->request_method $uri HTTP/$this->protocol_version";
    5693. -
    5694. $this->debug("HTTP request: $req");
    5695. -
    5696. $this->outgoing_payload = "$req\r\n";
    5697. -
    5698.  
    5699. -
    5700. // loop thru headers, serializing
    5701. -
    5702. foreach($this->outgoing_headers as $k => $v){
    5703. -
    5704. $hdr = $k.': '.$v;
    5705. -
    5706. $this->debug("HTTP header: $hdr");
    5707. -
    5708. $this->outgoing_payload .= "$hdr\r\n";
    5709. -
    5710. }
    5711. -
    5712.  
    5713. -
    5714. // add any cookies
    5715. -
    5716. if ($cookie_str != '') {
    5717. -
    5718. $hdr = 'Cookie: '.$cookie_str;
    5719. -
    5720. $this->debug("HTTP header: $hdr");
    5721. -
    5722. $this->outgoing_payload .= "$hdr\r\n";
    5723. -
    5724. }
    5725. -
    5726.  
    5727. -
    5728. // header/body separator
    5729. -
    5730. $this->outgoing_payload .= "\r\n";
    5731. -
    5732. -
    5733. // add data
    5734. -
    5735. $this->outgoing_payload .= $data;
    5736. -
    5737. }
    5738. -
    5739.  
    5740. -
    5741. /**
    5742. -
    5743. * sends the SOAP request via HTTP[S]
    5744. -
    5745. *
    5746. -
    5747. * @param string $data message data
    5748. -
    5749. * @param array $cookies cookies to send
    5750. -
    5751. * @return boolean true if OK, false if problem
    5752. -
    5753. * @access private
    5754. -
    5755. */
    5756. -
    5757. function sendRequest($data, $cookies = NULL) {
    5758. -
    5759. // build cookie string
    5760. -
    5761. $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
    5762. -
    5763.  
    5764. -
    5765. // build payload
    5766. -
    5767. $this->buildPayload($data, $cookie_str);
    5768. -
    5769.  
    5770. -
    5771. if ($this->io_method() == 'socket') {
    5772. -
    5773. // send payload
    5774. -
    5775. if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
    5776. -
    5777. $this->setError('couldn\'t write message data to socket');
    5778. -
    5779. $this->debug('couldn\'t write message data to socket');
    5780. -
    5781. return false;
    5782. -
    5783. }
    5784. -
    5785. $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
    5786. -
    5787. return true;
    5788. -
    5789. } else if ($this->io_method() == 'curl') {
    5790. -
    5791. // set payload
    5792. -
    5793. // cURL does say this should only be the verb, and in fact it
    5794. -
    5795. // turns out that the URI and HTTP version are appended to this, which
    5796. -
    5797. // some servers refuse to work with (so we no longer use this method!)
    5798. -
    5799. //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
    5800. -
    5801. $curl_headers = array();
    5802. -
    5803. foreach($this->outgoing_headers as $k => $v){
    5804. -
    5805. if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
    5806. -
    5807. $this->debug("Skip cURL header $k: $v");
    5808. -
    5809. } else {
    5810. -
    5811. $curl_headers[] = "$k: $v";
    5812. -
    5813. }
    5814. -
    5815. }
    5816. -
    5817. if ($cookie_str != '') {
    5818. -
    5819. $curl_headers[] = 'Cookie: ' . $cookie_str;
    5820. -
    5821. }
    5822. -
    5823. $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
    5824. -
    5825. $this->debug('set cURL HTTP headers');
    5826. -
    5827. if ($this->request_method == "POST") {
    5828. -
    5829. $this->setCurlOption(CURLOPT_POST, 1);
    5830. -
    5831. $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
    5832. -
    5833. $this->debug('set cURL POST data');
    5834. -
    5835. } else {
    5836. -
    5837. }
    5838. -
    5839. // insert custom user-set cURL options
    5840. -
    5841. foreach ($this->ch_options as $key => $val) {
    5842. -
    5843. $this->setCurlOption($key, $val);
    5844. -
    5845. }
    5846. -
    5847.  
    5848. -
    5849. $this->debug('set cURL payload');
    5850. -
    5851. return true;
    5852. -
    5853. }
    5854. -
    5855. }
    5856. -
    5857.  
    5858. -
    5859. /**
    5860. -
    5861. * gets the SOAP response via HTTP[S]
    5862. -
    5863. *
    5864. -
    5865. * @return string the response (also sets member variables like incoming_payload)
    5866. -
    5867. * @access private
    5868. -
    5869. */
    5870. -
    5871. function getResponse(){
    5872. -
    5873. $this->incoming_payload = '';
    5874. -
    5875. -
    5876. if ($this->io_method() == 'socket') {
    5877. -
    5878. // loop until headers have been retrieved
    5879. -
    5880. $data = '';
    5881. -
    5882. while (!isset($lb)){
    5883. -
    5884.  
    5885. -
    5886. // We might EOF during header read.
    5887. -
    5888. if(feof($this->fp)) {
    5889. -
    5890. $this->incoming_payload = $data;
    5891. -
    5892. $this->debug('found no headers before EOF after length ' . strlen($data));
    5893. -
    5894. $this->debug("received before EOF:\n" . $data);
    5895. -
    5896. $this->setError('server failed to send headers');
    5897. -
    5898. return false;
    5899. -
    5900. }
    5901. -
    5902.  
    5903. -
    5904. $tmp = fgets($this->fp, 256);
    5905. -
    5906. $tmplen = strlen($tmp);
    5907. -
    5908. $this->debug("read line of $tmplen bytes: " . trim($tmp));
    5909. -
    5910.  
    5911. -
    5912. if ($tmplen == 0) {
    5913. -
    5914. $this->incoming_payload = $data;
    5915. -
    5916. $this->debug('socket read of headers timed out after length ' . strlen($data));
    5917. -
    5918. $this->debug("read before timeout: " . $data);
    5919. -
    5920. $this->setError('socket read of headers timed out');
    5921. -
    5922. return false;
    5923. -
    5924. }
    5925. -
    5926.  
    5927. -
    5928. $data .= $tmp;
    5929. -
    5930. $pos = strpos($data,"\r\n\r\n");
    5931. -
    5932. if($pos > 1){
    5933. -
    5934. $lb = "\r\n";
    5935. -
    5936. } else {
    5937. -
    5938. $pos = strpos($data,"\n\n");
    5939. -
    5940. if($pos > 1){
    5941. -
    5942. $lb = "\n";
    5943. -
    5944. }
    5945. -
    5946. }
    5947. -
    5948. // remove 100 headers
    5949. -
    5950. if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) {
    5951. -
    5952. unset($lb);
    5953. -
    5954. $data = '';
    5955. -
    5956. }//
    5957. -
    5958. }
    5959. -
    5960. // store header data
    5961. -
    5962. $this->incoming_payload .= $data;
    5963. -
    5964. $this->debug('found end of headers after length ' . strlen($data));
    5965. -
    5966. // process headers
    5967. -
    5968. $header_data = trim(substr($data,0,$pos));
    5969. -
    5970. $header_array = explode($lb,$header_data);
    5971. -
    5972. $this->incoming_headers = array();
    5973. -
    5974. $this->incoming_cookies = array();
    5975. -
    5976. foreach($header_array as $header_line){
    5977. -
    5978. $arr = explode(':',$header_line, 2);
    5979. -
    5980. if(count($arr) > 1){
    5981. -
    5982. $header_name = strtolower(trim($arr[0]));
    5983. -
    5984. $this->incoming_headers[$header_name] = trim($arr[1]);
    5985. -
    5986. if ($header_name == 'set-cookie') {
    5987. -
    5988. // TODO: allow multiple cookies from parseCookie
    5989. -
    5990. $cookie = $this->parseCookie(trim($arr[1]));
    5991. -
    5992. if ($cookie) {
    5993. -
    5994. $this->incoming_cookies[] = $cookie;
    5995. -
    5996. $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
    5997. -
    5998. } else {
    5999. -
    6000. $this->debug('did not find cookie in ' . trim($arr[1]));
    6001. -
    6002. }
    6003. -
    6004. }
    6005. -
    6006. } else if (isset($header_name)) {
    6007. -
    6008. // append continuation line to previous header
    6009. -
    6010. $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
    6011. -
    6012. }
    6013. -
    6014. }
    6015. -
    6016. -
    6017. // loop until msg has been received
    6018. -
    6019. if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
    6020. -
    6021. $content_length = 2147483647; // ignore any content-length header
    6022. -
    6023. $chunked = true;
    6024. -
    6025. $this->debug("want to read chunked content");
    6026. -
    6027. } elseif (isset($this->incoming_headers['content-length'])) {
    6028. -
    6029. $content_length = $this->incoming_headers['content-length'];
    6030. -
    6031. $chunked = false;
    6032. -
    6033. $this->debug("want to read content of length $content_length");
    6034. -
    6035. } else {
    6036. -
    6037. $content_length = 2147483647;
    6038. -
    6039. $chunked = false;
    6040. -
    6041. $this->debug("want to read content to EOF");
    6042. -
    6043. }
    6044. -
    6045. $data = '';
    6046. -
    6047. do {
    6048. -
    6049. if ($chunked) {
    6050. -
    6051. $tmp = fgets($this->fp, 256);
    6052. -
    6053. $tmplen = strlen($tmp);
    6054. -
    6055. $this->debug("read chunk line of $tmplen bytes");
    6056. -
    6057. if ($tmplen == 0) {
    6058. -
    6059. $this->incoming_payload = $data;
    6060. -
    6061. $this->debug('socket read of chunk length timed out after length ' . strlen($data));
    6062. -
    6063. $this->debug("read before timeout:\n" . $data);
    6064. -
    6065. $this->setError('socket read of chunk length timed out');
    6066. -
    6067. return false;
    6068. -
    6069. }
    6070. -
    6071. $content_length = hexdec(trim($tmp));
    6072. -
    6073. $this->debug("chunk length $content_length");
    6074. -
    6075. }
    6076. -
    6077. $strlen = 0;
    6078. -
    6079. while (($strlen < $content_length) && (!feof($this->fp))) {
    6080. -
    6081. $readlen = min(8192, $content_length - $strlen);
    6082. -
    6083. $tmp = fread($this->fp, $readlen);
    6084. -
    6085. $tmplen = strlen($tmp);
    6086. -
    6087. $this->debug("read buffer of $tmplen bytes");
    6088. -
    6089. if (($tmplen == 0) && (!feof($this->fp))) {
    6090. -
    6091. $this->incoming_payload = $data;
    6092. -
    6093. $this->debug('socket read of body timed out after length ' . strlen($data));
    6094. -
    6095. $this->debug("read before timeout:\n" . $data);
    6096. -
    6097. $this->setError('socket read of body timed out');
    6098. -
    6099. return false;
    6100. -
    6101. }
    6102. -
    6103. $strlen += $tmplen;
    6104. -
    6105. $data .= $tmp;
    6106. -
    6107. }
    6108. -
    6109. if ($chunked && ($content_length > 0)) {
    6110. -
    6111. $tmp = fgets($this->fp, 256);
    6112. -
    6113. $tmplen = strlen($tmp);
    6114. -
    6115. $this->debug("read chunk terminator of $tmplen bytes");
    6116. -
    6117. if ($tmplen == 0) {
    6118. -
    6119. $this->incoming_payload = $data;
    6120. -
    6121. $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
    6122. -
    6123. $this->debug("read before timeout:\n" . $data);
    6124. -
    6125. $this->setError('socket read of chunk terminator timed out');
    6126. -
    6127. return false;
    6128. -
    6129. }
    6130. -
    6131. }
    6132. -
    6133. } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
    6134. -
    6135. if (feof($this->fp)) {
    6136. -
    6137. $this->debug('read to EOF');
    6138. -
    6139. }
    6140. -
    6141. $this->debug('read body of length ' . strlen($data));
    6142. -
    6143. $this->incoming_payload .= $data;
    6144. -
    6145. $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
    6146. -
    6147. -
    6148. // close filepointer
    6149. -
    6150. if(
    6151. -
    6152. (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
    6153. -
    6154. (! $this->persistentConnection) || feof($this->fp)){
    6155. -
    6156. fclose($this->fp);
    6157. -
    6158. $this->fp = false;
    6159. -
    6160. $this->debug('closed socket');
    6161. -
    6162. }
    6163. -
    6164. -
    6165. // connection was closed unexpectedly
    6166. -
    6167. if($this->incoming_payload == ''){
    6168. -
    6169. $this->setError('no response from server');
    6170. -
    6171. return false;
    6172. -
    6173. }
    6174. -
    6175. -
    6176. // decode transfer-encoding
    6177. -
    6178. // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
    6179. -
    6180. // if(!$data = $this->decodeChunked($data, $lb)){
    6181. -
    6182. // $this->setError('Decoding of chunked data failed');
    6183. -
    6184. // return false;
    6185. -
    6186. // }
    6187. -
    6188. //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
    6189. -
    6190. // set decoded payload
    6191. -
    6192. // $this->incoming_payload = $header_data.$lb.$lb.$data;
    6193. -
    6194. // }
    6195. -
    6196. -
    6197. } else if ($this->io_method() == 'curl') {
    6198. -
    6199. // send and receive
    6200. -
    6201. $this->debug('send and receive with cURL');
    6202. -
    6203. $this->incoming_payload = curl_exec($this->ch);
    6204. -
    6205. $data = $this->incoming_payload;
    6206. -
    6207.  
    6208. -
    6209. $cErr = curl_error($this->ch);
    6210. -
    6211. if ($cErr != '') {
    6212. -
    6213. $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
    6214. -
    6215. // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
    6216. -
    6217. foreach(curl_getinfo($this->ch) as $k => $v){
    6218. -
    6219. $err .= "$k: $v<br>";
    6220. -
    6221. }
    6222. -
    6223. $this->debug($err);
    6224. -
    6225. $this->setError($err);
    6226. -
    6227. curl_close($this->ch);
    6228. -
    6229. return false;
    6230. -
    6231. } else {
    6232. -
    6233. //echo '<pre>';
    6234. -
    6235. //var_dump(curl_getinfo($this->ch));
    6236. -
    6237. //echo '</pre>';
    6238. -
    6239. }
    6240. -
    6241. // close curl
    6242. -
    6243. $this->debug('No cURL error, closing cURL');
    6244. -
    6245. curl_close($this->ch);
    6246. -
    6247. -
    6248. // try removing skippable headers
    6249. -
    6250. $savedata = $data;
    6251. -
    6252. while ($this->isSkippableCurlHeader($data)) {
    6253. -
    6254. $this->debug("Found HTTP header to skip");
    6255. -
    6256. if ($pos = strpos($data,"\r\n\r\n")) {
    6257. -
    6258. $data = ltrim(substr($data,$pos));
    6259. -
    6260. } elseif($pos = strpos($data,"\n\n") ) {
    6261. -
    6262. $data = ltrim(substr($data,$pos));
    6263. -
    6264. }
    6265. -
    6266. }
    6267. -
    6268.  
    6269. -
    6270. if ($data == '') {
    6271. -
    6272. // have nothing left; just remove 100 header(s)
    6273. -
    6274. $data = $savedata;
    6275. -
    6276. while (preg_match('/^HTTP\/1.1 100/',$data)) {
    6277. -
    6278. if ($pos = strpos($data,"\r\n\r\n")) {
    6279. -
    6280. $data = ltrim(substr($data,$pos));
    6281. -
    6282. } elseif($pos = strpos($data,"\n\n") ) {
    6283. -
    6284. $data = ltrim(substr($data,$pos));
    6285. -
    6286. }
    6287. -
    6288. }
    6289. -
    6290. }
    6291. -
    6292. -
    6293. // separate content from HTTP headers
    6294. -
    6295. if ($pos = strpos($data,"\r\n\r\n")) {
    6296. -
    6297. $lb = "\r\n";
    6298. -
    6299. } elseif( $pos = strpos($data,"\n\n")) {
    6300. -
    6301. $lb = "\n";
    6302. -
    6303. } else {
    6304. -
    6305. $this->debug('no proper separation of headers and document');
    6306. -
    6307. $this->setError('no proper separation of headers and document');
    6308. -
    6309. return false;
    6310. -
    6311. }
    6312. -
    6313. $header_data = trim(substr($data,0,$pos));
    6314. -
    6315. $header_array = explode($lb,$header_data);
    6316. -
    6317. $data = ltrim(substr($data,$pos));
    6318. -
    6319. $this->debug('found proper separation of headers and document');
    6320. -
    6321. $this->debug('cleaned data, stringlen: '.strlen($data));
    6322. -
    6323. // clean headers
    6324. -
    6325. foreach ($header_array as $header_line) {
    6326. -
    6327. $arr = explode(':',$header_line,2);
    6328. -
    6329. if(count($arr) > 1){
    6330. -
    6331. $header_name = strtolower(trim($arr[0]));
    6332. -
    6333. $this->incoming_headers[$header_name] = trim($arr[1]);
    6334. -
    6335. if ($header_name == 'set-cookie') {
    6336. -
    6337. // TODO: allow multiple cookies from parseCookie
    6338. -
    6339. $cookie = $this->parseCookie(trim($arr[1]));
    6340. -
    6341. if ($cookie) {
    6342. -
    6343. $this->incoming_cookies[] = $cookie;
    6344. -
    6345. $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
    6346. -
    6347. } else {
    6348. -
    6349. $this->debug('did not find cookie in ' . trim($arr[1]));
    6350. -
    6351. }
    6352. -
    6353. }
    6354. -
    6355. } else if (isset($header_name)) {
    6356. -
    6357. // append continuation line to previous header
    6358. -
    6359. $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
    6360. -
    6361. }
    6362. -
    6363. }
    6364. -
    6365. }
    6366. -
    6367.  
    6368. -
    6369. $this->response_status_line = $header_array[0];
    6370. -
    6371. $arr = explode(' ', $this->response_status_line, 3);
    6372. -
    6373. $http_version = $arr[0];
    6374. -
    6375. $http_status = intval($arr[1]);
    6376. -
    6377. $http_reason = count($arr) > 2 ? $arr[2] : '';
    6378. -
    6379.  
    6380. -
    6381. // see if we need to resend the request with http digest authentication
    6382. -
    6383. if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
    6384. -
    6385. $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
    6386. -
    6387. $this->setURL($this->incoming_headers['location']);
    6388. -
    6389. $this->tryagain = true;
    6390. -
    6391. return false;
    6392. -
    6393. }
    6394. -
    6395.  
    6396. -
    6397. // see if we need to resend the request with http digest authentication
    6398. -
    6399. if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
    6400. -
    6401. $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
    6402. -
    6403. if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
    6404. -
    6405. $this->debug('Server wants digest authentication');
    6406. -
    6407. // remove "Digest " from our elements
    6408. -
    6409. $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
    6410. -
    6411. -
    6412. // parse elements into array
    6413. -
    6414. $digestElements = explode(',', $digestString);
    6415. -
    6416. foreach ($digestElements as $val) {
    6417. -
    6418. $tempElement = explode('=', trim($val), 2);
    6419. -
    6420. $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
    6421. -
    6422. }
    6423. -
    6424.  
    6425. -
    6426. // should have (at least) qop, realm, nonce
    6427. -
    6428. if (isset($digestRequest['nonce'])) {
    6429. -
    6430. $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
    6431. -
    6432. $this->tryagain = true;
    6433. -
    6434. return false;
    6435. -
    6436. }
    6437. -
    6438. }
    6439. -
    6440. $this->debug('HTTP authentication failed');
    6441. -
    6442. $this->setError('HTTP authentication failed');
    6443. -
    6444. return false;
    6445. -
    6446. }
    6447. -
    6448. -
    6449. if (
    6450. -
    6451. ($http_status >= 300 && $http_status <= 307) ||
    6452. -
    6453. ($http_status >= 400 && $http_status <= 417) ||
    6454. -
    6455. ($http_status >= 501 && $http_status <= 505)
    6456. -
    6457. ) {
    6458. -
    6459. $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
    6460. -
    6461. return false;
    6462. -
    6463. }
    6464. -
    6465.  
    6466. -
    6467. // decode content-encoding
    6468. -
    6469. if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
    6470. -
    6471. if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
    6472. -
    6473. // if decoding works, use it. else assume data wasn't gzencoded
    6474. -
    6475. if(function_exists('gzinflate')){
    6476. -
    6477. //$timer->setMarker('starting decoding of gzip/deflated content');
    6478. -
    6479. // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
    6480. -
    6481. // this means there are no Zlib headers, although there should be
    6482. -
    6483. $this->debug('The gzinflate function exists');
    6484. -
    6485. $datalen = strlen($data);
    6486. -
    6487. if ($this->incoming_headers['content-encoding'] == 'deflate') {
    6488. -
    6489. if ($degzdata = @gzinflate($data)) {
    6490. -
    6491. $data = $degzdata;
    6492. -
    6493. $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
    6494. -
    6495. if (strlen($data) < $datalen) {
    6496. -
    6497. // test for the case that the payload has been compressed twice
    6498. -
    6499. $this->debug('The inflated payload is smaller than the gzipped one; try again');
    6500. -
    6501. if ($degzdata = @gzinflate($data)) {
    6502. -
    6503. $data = $degzdata;
    6504. -
    6505. $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
    6506. -
    6507. }
    6508. -
    6509. }
    6510. -
    6511. } else {
    6512. -
    6513. $this->debug('Error using gzinflate to inflate the payload');
    6514. -
    6515. $this->setError('Error using gzinflate to inflate the payload');
    6516. -
    6517. }
    6518. -
    6519. } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
    6520. -
    6521. if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
    6522. -
    6523. $data = $degzdata;
    6524. -
    6525. $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
    6526. -
    6527. if (strlen($data) < $datalen) {
    6528. -
    6529. // test for the case that the payload has been compressed twice
    6530. -
    6531. $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
    6532. -
    6533. if ($degzdata = @gzinflate(substr($data, 10))) {
    6534. -
    6535. $data = $degzdata;
    6536. -
    6537. $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
    6538. -
    6539. }
    6540. -
    6541. }
    6542. -
    6543. } else {
    6544. -
    6545. $this->debug('Error using gzinflate to un-gzip the payload');
    6546. -
    6547. $this->setError('Error using gzinflate to un-gzip the payload');
    6548. -
    6549. }
    6550. -
    6551. }
    6552. -
    6553. //$timer->setMarker('finished decoding of gzip/deflated content');
    6554. -
    6555. //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
    6556. -
    6557. // set decoded payload
    6558. -
    6559. $this->incoming_payload = $header_data.$lb.$lb.$data;
    6560. -
    6561. } else {
    6562. -
    6563. $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
    6564. -
    6565. $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
    6566. -
    6567. }
    6568. -
    6569. } else {
    6570. -
    6571. $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
    6572. -
    6573. $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
    6574. -
    6575. }
    6576. -
    6577. } else {
    6578. -
    6579. $this->debug('No Content-Encoding header');
    6580. -
    6581. }
    6582. -
    6583. -
    6584. if(strlen($data) == 0){
    6585. -
    6586. $this->debug('no data after headers!');
    6587. -
    6588. $this->setError('no data present after HTTP headers');
    6589. -
    6590. return false;
    6591. -
    6592. }
    6593. -
    6594. -
    6595. return $data;
    6596. -
    6597. }
    6598. -
    6599.  
    6600. -
    6601. /**
    6602. -
    6603. * sets the content-type for the SOAP message to be sent
    6604. -
    6605. *
    6606. -
    6607. * @param string $type the content type, MIME style
    6608. -
    6609. * @param mixed $charset character set used for encoding (or false)
    6610. -
    6611. * @access public
    6612. -
    6613. */
    6614. -
    6615. function setContentType($type, $charset = false) {
    6616. -
    6617. $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
    6618. -
    6619. }
    6620. -
    6621.  
    6622. -
    6623. /**
    6624. -
    6625. * specifies that an HTTP persistent connection should be used
    6626. -
    6627. *
    6628. -
    6629. * @return boolean whether the request was honored by this method.
    6630. -
    6631. * @access public
    6632. -
    6633. */
    6634. -
    6635. function usePersistentConnection(){
    6636. -
    6637. if (isset($this->outgoing_headers['Accept-Encoding'])) {
    6638. -
    6639. return false;
    6640. -
    6641. }
    6642. -
    6643. $this->protocol_version = '1.1';
    6644. -
    6645. $this->persistentConnection = true;
    6646. -
    6647. $this->setHeader('Connection', 'Keep-Alive');
    6648. -
    6649. return true;
    6650. -
    6651. }
    6652. -
    6653.  
    6654. -
    6655. /**
    6656. -
    6657. * parse an incoming Cookie into it's parts
    6658. -
    6659. *
    6660. -
    6661. * @param string $cookie_str content of cookie
    6662. -
    6663. * @return array with data of that cookie
    6664. -
    6665. * @access private
    6666. -
    6667. */
    6668. -
    6669. /*
    6670. -
    6671. * TODO: allow a Set-Cookie string to be parsed into multiple cookies
    6672. -
    6673. */
    6674. -
    6675. function parseCookie($cookie_str) {
    6676. -
    6677. $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
    6678. -
    6679. $data = preg_split('/;/', $cookie_str);
    6680. -
    6681. $value_str = $data[0];
    6682. -
    6683.  
    6684. -
    6685. $cookie_param = 'domain=';
    6686. -
    6687. $start = strpos($cookie_str, $cookie_param);
    6688. -
    6689. if ($start > 0) {
    6690. -
    6691. $domain = substr($cookie_str, $start + strlen($cookie_param));
    6692. -
    6693. $domain = substr($domain, 0, strpos($domain, ';'));
    6694. -
    6695. } else {
    6696. -
    6697. $domain = '';
    6698. -
    6699. }
    6700. -
    6701.  
    6702. -
    6703. $cookie_param = 'expires=';
    6704. -
    6705. $start = strpos($cookie_str, $cookie_param);
    6706. -
    6707. if ($start > 0) {
    6708. -
    6709. $expires = substr($cookie_str, $start + strlen($cookie_param));
    6710. -
    6711. $expires = substr($expires, 0, strpos($expires, ';'));
    6712. -
    6713. } else {
    6714. -
    6715. $expires = '';
    6716. -
    6717. }
    6718. -
    6719.  
    6720. -
    6721. $cookie_param = 'path=';
    6722. -
    6723. $start = strpos($cookie_str, $cookie_param);
    6724. -
    6725. if ( $start > 0 ) {
    6726. -
    6727. $path = substr($cookie_str, $start + strlen($cookie_param));
    6728. -
    6729. $path = substr($path, 0, strpos($path, ';'));
    6730. -
    6731. } else {
    6732. -
    6733. $path = '/';
    6734. -
    6735. }
    6736. -
    6737. -
    6738. $cookie_param = ';secure;';
    6739. -
    6740. if (strpos($cookie_str, $cookie_param) !== FALSE) {
    6741. -
    6742. $secure = true;
    6743. -
    6744. } else {
    6745. -
    6746. $secure = false;
    6747. -
    6748. }
    6749. -
    6750.  
    6751. -
    6752. $sep_pos = strpos($value_str, '=');
    6753. -
    6754.  
    6755. -
    6756. if ($sep_pos) {
    6757. -
    6758. $name = substr($value_str, 0, $sep_pos);
    6759. -
    6760. $value = substr($value_str, $sep_pos + 1);
    6761. -
    6762. $cookie= array( 'name' => $name,
    6763. -
    6764. 'value' => $value,
    6765. -
    6766. 'domain' => $domain,
    6767. -
    6768. 'path' => $path,
    6769. -
    6770. 'expires' => $expires,
    6771. -
    6772. 'secure' => $secure
    6773. -
    6774. );
    6775. -
    6776. return $cookie;
    6777. -
    6778. }
    6779. -
    6780. return false;
    6781. -
    6782. }
    6783. -
    6784. -
    6785. /**
    6786. -
    6787. * sort out cookies for the current request
    6788. -
    6789. *
    6790. -
    6791. * @param array $cookies array with all cookies
    6792. -
    6793. * @param boolean $secure is the send-content secure or not?
    6794. -
    6795. * @return string for Cookie-HTTP-Header
    6796. -
    6797. * @access private
    6798. -
    6799. */
    6800. -
    6801. function getCookiesForRequest($cookies, $secure=false) {
    6802. -
    6803. $cookie_str = '';
    6804. -
    6805. if ((! is_null($cookies)) && (is_array($cookies))) {
    6806. -
    6807. foreach ($cookies as $cookie) {
    6808. -
    6809. if (! is_array($cookie)) {
    6810. -
    6811. continue;
    6812. -
    6813. }
    6814. -
    6815. $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
    6816. -
    6817. if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
    6818. -
    6819. if (strtotime($cookie['expires']) <= time()) {
    6820. -
    6821. $this->debug('cookie has expired');
    6822. -
    6823. continue;
    6824. -
    6825. }
    6826. -
    6827. }
    6828. -
    6829. if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
    6830. -
    6831. $domain = preg_quote($cookie['domain']);
    6832. -
    6833. if (! preg_match("'.*$domain$'i", $this->host)) {
    6834. -
    6835. $this->debug('cookie has different domain');
    6836. -
    6837. continue;
    6838. -
    6839. }
    6840. -
    6841. }
    6842. -
    6843. if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
    6844. -
    6845. $path = preg_quote($cookie['path']);
    6846. -
    6847. if (! preg_match("'^$path.*'i", $this->path)) {
    6848. -
    6849. $this->debug('cookie is for a different path');
    6850. -
    6851. continue;
    6852. -
    6853. }
    6854. -
    6855. }
    6856. -
    6857. if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
    6858. -
    6859. $this->debug('cookie is secure, transport is not');
    6860. -
    6861. continue;
    6862. -
    6863. }
    6864. -
    6865. $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
    6866. -
    6867. $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
    6868. -
    6869. }
    6870. -
    6871. }
    6872. -
    6873. return $cookie_str;
    6874. -
    6875. }
    6876. -
    6877. }
    6878. -
    6879.  
    6880. -
    6881. ?><?php
    6882. -
    6883.  
    6884. -
    6885.  
    6886. -
    6887.  
    6888. -
    6889. /**
    6890. -
    6891. *
    6892. -
    6893. * nusoap_server allows the user to create a SOAP server
    6894. -
    6895. * that is capable of receiving messages and returning responses
    6896. -
    6897. *
    6898. -
    6899. * @author Dietrich Ayala <dietrich@ganx4.com>
    6900. -
    6901. * @author Scott Nichol <snichol@users.sourceforge.net>
    6902. -
    6903. * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    6904. -
    6905. * @access public
    6906. -
    6907. */
    6908. -
    6909. class nusoap_server extends nusoap_base {
    6910. -
    6911. /**
    6912. -
    6913. * HTTP headers of request
    6914. -
    6915. * @var array
    6916. -
    6917. * @access private
    6918. -
    6919. */
    6920. -
    6921. var $headers = array();
    6922. -
    6923. /**
    6924. -
    6925. * HTTP request
    6926. -
    6927. * @var string
    6928. -
    6929. * @access private
    6930. -
    6931. */
    6932. -
    6933. var $request = '';
    6934. -
    6935. /**
    6936. -
    6937. * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
    6938. -
    6939. * @var string
    6940. -
    6941. * @access public
    6942. -
    6943. */
    6944. -
    6945. var $requestHeaders = '';
    6946. -
    6947. /**
    6948. -
    6949. * SOAP Headers from request (parsed)
    6950. -
    6951. * @var mixed
    6952. -
    6953. * @access public
    6954. -
    6955. */
    6956. -
    6957. var $requestHeader = NULL;
    6958. -
    6959. /**
    6960. -
    6961. * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
    6962. -
    6963. * @var string
    6964. -
    6965. * @access public
    6966. -
    6967. */
    6968. -
    6969. var $document = '';
    6970. -
    6971. /**
    6972. -
    6973. * SOAP payload for request (text)
    6974. -
    6975. * @var string
    6976. -
    6977. * @access public
    6978. -
    6979. */
    6980. -
    6981. var $requestSOAP = '';
    6982. -
    6983. /**
    6984. -
    6985. * requested method namespace URI
    6986. -
    6987. * @var string
    6988. -
    6989. * @access private
    6990. -
    6991. */
    6992. -
    6993. var $methodURI = '';
    6994. -
    6995. /**
    6996. -
    6997. * name of method requested
    6998. -
    6999. * @var string
    7000. -
    7001. * @access private
    7002. -
    7003. */
    7004. -
    7005. var $methodname = '';
    7006. -
    7007. /**
    7008. -
    7009. * method parameters from request
    7010. -
    7011. * @var array
    7012. -
    7013. * @access private
    7014. -
    7015. */
    7016. -
    7017. var $methodparams = array();
    7018. -
    7019. /**
    7020. -
    7021. * SOAP Action from request
    7022. -
    7023. * @var string
    7024. -
    7025. * @access private
    7026. -
    7027. */
    7028. -
    7029. var $SOAPAction = '';
    7030. -
    7031. /**
    7032. -
    7033. * character set encoding of incoming (request) messages
    7034. -
    7035. * @var string
    7036. -
    7037. * @access public
    7038. -
    7039. */
    7040. -
    7041. var $xml_encoding = '';
    7042. -
    7043. /**
    7044. -
    7045. * toggles whether the parser decodes element content w/ utf8_decode()
    7046. -
    7047. * @var boolean
    7048. -
    7049. * @access public
    7050. -
    7051. */
    7052. -
    7053. var $decode_utf8 = true;
    7054. -
    7055.  
    7056. -
    7057. /**
    7058. -
    7059. * HTTP headers of response
    7060. -
    7061. * @var array
    7062. -
    7063. * @access public
    7064. -
    7065. */
    7066. -
    7067. var $outgoing_headers = array();
    7068. -
    7069. /**
    7070. -
    7071. * HTTP response
    7072. -
    7073. * @var string
    7074. -
    7075. * @access private
    7076. -
    7077. */
    7078. -
    7079. var $response = '';
    7080. -
    7081. /**
    7082. -
    7083. * SOAP headers for response (text or array of soapval or associative array)
    7084. -
    7085. * @var mixed
    7086. -
    7087. * @access public
    7088. -
    7089. */
    7090. -
    7091. var $responseHeaders = '';
    7092. -
    7093. /**
    7094. -
    7095. * SOAP payload for response (text)
    7096. -
    7097. * @var string
    7098. -
    7099. * @access private
    7100. -
    7101. */
    7102. -
    7103. var $responseSOAP = '';
    7104. -
    7105. /**
    7106. -
    7107. * method return value to place in response
    7108. -
    7109. * @var mixed
    7110. -
    7111. * @access private
    7112. -
    7113. */
    7114. -
    7115. var $methodreturn = false;
    7116. -
    7117. /**
    7118. -
    7119. * whether $methodreturn is a string of literal XML
    7120. -
    7121. * @var boolean
    7122. -
    7123. * @access public
    7124. -
    7125. */
    7126. -
    7127. var $methodreturnisliteralxml = false;
    7128. -
    7129. /**
    7130. -
    7131. * SOAP fault for response (or false)
    7132. -
    7133. * @var mixed
    7134. -
    7135. * @access private
    7136. -
    7137. */
    7138. -
    7139. var $fault = false;
    7140. -
    7141. /**
    7142. -
    7143. * text indication of result (for debugging)
    7144. -
    7145. * @var string
    7146. -
    7147. * @access private
    7148. -
    7149. */
    7150. -
    7151. var $result = 'successful';
    7152. -
    7153.  
    7154. -
    7155. /**
    7156. -
    7157. * assoc array of operations => opData; operations are added by the register()
    7158. -
    7159. * method or by parsing an external WSDL definition
    7160. -
    7161. * @var array
    7162. -
    7163. * @access private
    7164. -
    7165. */
    7166. -
    7167. var $operations = array();
    7168. -
    7169. /**
    7170. -
    7171. * wsdl instance (if one)
    7172. -
    7173. * @var mixed
    7174. -
    7175. * @access private
    7176. -
    7177. */
    7178. -
    7179. var $wsdl = false;
    7180. -
    7181. /**
    7182. -
    7183. * URL for WSDL (if one)
    7184. -
    7185. * @var mixed
    7186. -
    7187. * @access private
    7188. -
    7189. */
    7190. -
    7191. var $externalWSDLURL = false;
    7192. -
    7193. /**
    7194. -
    7195. * whether to append debug to response as XML comment
    7196. -
    7197. * @var boolean
    7198. -
    7199. * @access public
    7200. -
    7201. */
    7202. -
    7203. var $debug_flag = false;
    7204. -
    7205.  
    7206. -
    7207.  
    7208. -
    7209. /**
    7210. -
    7211. * constructor
    7212. -
    7213. * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
    7214. -
    7215. *
    7216. -
    7217. * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
    7218. -
    7219. * @access public
    7220. -
    7221. */
    7222. -
    7223. function nusoap_server($wsdl=false){
    7224. -
    7225. parent::nusoap_base();
    7226. -
    7227. // turn on debugging?
    7228. -
    7229. global $debug;
    7230. -
    7231. global $HTTP_SERVER_VARS;
    7232. -
    7233.  
    7234. -
    7235. if (isset($_SERVER)) {
    7236. -
    7237. $this->debug("_SERVER is defined:");
    7238. -
    7239. $this->appendDebug($this->varDump($_SERVER));
    7240. -
    7241. } elseif (isset($HTTP_SERVER_VARS)) {
    7242. -
    7243. $this->debug("HTTP_SERVER_VARS is defined:");
    7244. -
    7245. $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
    7246. -
    7247. } else {
    7248. -
    7249. $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
    7250. -
    7251. }
    7252. -
    7253.  
    7254. -
    7255. if (isset($debug)) {
    7256. -
    7257. $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
    7258. -
    7259. $this->debug_flag = $debug;
    7260. -
    7261. } elseif (isset($_SERVER['QUERY_STRING'])) {
    7262. -
    7263. $qs = explode('&', $_SERVER['QUERY_STRING']);
    7264. -
    7265. foreach ($qs as $v) {
    7266. -
    7267. if (substr($v, 0, 6) == 'debug=') {
    7268. -
    7269. $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
    7270. -
    7271. $this->debug_flag = substr($v, 6);
    7272. -
    7273. }
    7274. -
    7275. }
    7276. -
    7277. } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
    7278. -
    7279. $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
    7280. -
    7281. foreach ($qs as $v) {
    7282. -
    7283. if (substr($v, 0, 6) == 'debug=') {
    7284. -
    7285. $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
    7286. -
    7287. $this->debug_flag = substr($v, 6);
    7288. -
    7289. }
    7290. -
    7291. }
    7292. -
    7293. }
    7294. -
    7295.  
    7296. -
    7297. // wsdl
    7298. -
    7299. if($wsdl){
    7300. -
    7301. $this->debug("In nusoap_server, WSDL is specified");
    7302. -
    7303. if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
    7304. -
    7305. $this->wsdl = $wsdl;
    7306. -
    7307. $this->externalWSDLURL = $this->wsdl->wsdl;
    7308. -
    7309. $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
    7310. -
    7311. } else {
    7312. -
    7313. $this->debug('Create wsdl from ' . $wsdl);
    7314. -
    7315. $this->wsdl = new wsdl($wsdl);
    7316. -
    7317. $this->externalWSDLURL = $wsdl;
    7318. -
    7319. }
    7320. -
    7321. $this->appendDebug($this->wsdl->getDebug());
    7322. -
    7323. $this->wsdl->clearDebug();
    7324. -
    7325. if($err = $this->wsdl->getError()){
    7326. -
    7327. die('WSDL ERROR: '.$err);
    7328. -
    7329. }
    7330. -
    7331. }
    7332. -
    7333. }
    7334. -
    7335.  
    7336. -
    7337. /**
    7338. -
    7339. * processes request and returns response
    7340. -
    7341. *
    7342. -
    7343. * @param string $data usually is the value of $HTTP_RAW_POST_DATA
    7344. -
    7345. * @access public
    7346. -
    7347. */
    7348. -
    7349. function service($data){
    7350. -
    7351. global $HTTP_SERVER_VARS;
    7352. -
    7353.  
    7354. -
    7355. if (isset($_SERVER['REQUEST_METHOD'])) {
    7356. -
    7357. $rm = $_SERVER['REQUEST_METHOD'];
    7358. -
    7359. } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
    7360. -
    7361. $rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
    7362. -
    7363. } else {
    7364. -
    7365. $rm = '';
    7366. -
    7367. }
    7368. -
    7369.  
    7370. -
    7371. if (isset($_SERVER['QUERY_STRING'])) {
    7372. -
    7373. $qs = $_SERVER['QUERY_STRING'];
    7374. -
    7375. } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
    7376. -
    7377. $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
    7378. -
    7379. } else {
    7380. -
    7381. $qs = '';
    7382. -
    7383. }
    7384. -
    7385. $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
    7386. -
    7387.  
    7388. -
    7389. if ($rm == 'POST') {
    7390. -
    7391. $this->debug("In service, invoke the request");
    7392. -
    7393. $this->parse_request($data);
    7394. -
    7395. if (! $this->fault) {
    7396. -
    7397. $this->invoke_method();
    7398. -
    7399. }
    7400. -
    7401. if (! $this->fault) {
    7402. -
    7403. $this->serialize_return();
    7404. -
    7405. }
    7406. -
    7407. $this->send_response();
    7408. -
    7409. } elseif (preg_match('/wsdl/', $qs) ){
    7410. -
    7411. $this->debug("In service, this is a request for WSDL");
    7412. -
    7413. if ($this->externalWSDLURL){
    7414. -
    7415. if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
    7416. -
    7417. $this->debug("In service, re-direct for WSDL");
    7418. -
    7419. header('Location: '.$this->externalWSDLURL);
    7420. -
    7421. } else { // assume file
    7422. -
    7423. $this->debug("In service, use file passthru for WSDL");
    7424. -
    7425. header("Content-Type: text/xml\r\n");
    7426. -
    7427. $pos = strpos($this->externalWSDLURL, "file://");
    7428. -
    7429. if ($pos === false) {
    7430. -
    7431. $filename = $this->externalWSDLURL;
    7432. -
    7433. } else {
    7434. -
    7435. $filename = substr($this->externalWSDLURL, $pos + 7);
    7436. -
    7437. }
    7438. -
    7439. $fp = fopen($this->externalWSDLURL, 'r');
    7440. -
    7441. fpassthru($fp);
    7442. -
    7443. }
    7444. -
    7445. } elseif ($this->wsdl) {
    7446. -
    7447. $this->debug("In service, serialize WSDL");
    7448. -
    7449. header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
    7450. -
    7451. print $this->wsdl->serialize($this->debug_flag);
    7452. -
    7453. if ($this->debug_flag) {
    7454. -
    7455. $this->debug('wsdl:');
    7456. -
    7457. $this->appendDebug($this->varDump($this->wsdl));
    7458. -
    7459. print $this->getDebugAsXMLComment();
    7460. -
    7461. }
    7462. -
    7463. } else {
    7464. -
    7465. $this->debug("In service, there is no WSDL");
    7466. -
    7467. header("Content-Type: text/html; charset=ISO-8859-1\r\n");
    7468. -
    7469. print "This service does not provide WSDL";
    7470. -
    7471. }
    7472. -
    7473. } elseif ($this->wsdl) {
    7474. -
    7475. $this->debug("In service, return Web description");
    7476. -
    7477. print $this->wsdl->webDescription();
    7478. -
    7479. } else {
    7480. -
    7481. $this->debug("In service, no Web description");
    7482. -
    7483. header("Content-Type: text/html; charset=ISO-8859-1\r\n");
    7484. -
    7485. print "This service does not provide a Web description";
    7486. -
    7487. }
    7488. -
    7489. }
    7490. -
    7491.  
    7492. -
    7493. /**
    7494. -
    7495. * parses HTTP request headers.
    7496. -
    7497. *
    7498. -
    7499. * The following fields are set by this function (when successful)
    7500. -
    7501. *
    7502. -
    7503. * headers
    7504. -
    7505. * request
    7506. -
    7507. * xml_encoding
    7508. -
    7509. * SOAPAction
    7510. -
    7511. *
    7512. -
    7513. * @access private
    7514. -
    7515. */
    7516. -
    7517. function parse_http_headers() {
    7518. -
    7519. global $HTTP_SERVER_VARS;
    7520. -
    7521.  
    7522. -
    7523. $this->request = '';
    7524. -
    7525. $this->SOAPAction = '';
    7526. -
    7527. if(function_exists('getallheaders')){
    7528. -
    7529. $this->debug("In parse_http_headers, use getallheaders");
    7530. -
    7531. $headers = getallheaders();
    7532. -
    7533. foreach($headers as $k=>$v){
    7534. -
    7535. $k = strtolower($k);
    7536. -
    7537. $this->headers[$k] = $v;
    7538. -
    7539. $this->request .= "$k: $v\r\n";
    7540. -
    7541. $this->debug("$k: $v");
    7542. -
    7543. }
    7544. -
    7545. // get SOAPAction header
    7546. -
    7547. if(isset($this->headers['soapaction'])){
    7548. -
    7549. $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
    7550. -
    7551. }
    7552. -
    7553. // get the character encoding of the incoming request
    7554. -
    7555. if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
    7556. -
    7557. $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
    7558. -
    7559. if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
    7560. -
    7561. $this->xml_encoding = strtoupper($enc);
    7562. -
    7563. } else {
    7564. -
    7565. $this->xml_encoding = 'US-ASCII';
    7566. -
    7567. }
    7568. -
    7569. } else {
    7570. -
    7571. // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
    7572. -
    7573. $this->xml_encoding = 'ISO-8859-1';
    7574. -
    7575. }
    7576. -
    7577. } elseif(isset($_SERVER) && is_array($_SERVER)){
    7578. -
    7579. $this->debug("In parse_http_headers, use _SERVER");
    7580. -
    7581. foreach ($_SERVER as $k => $v) {
    7582. -
    7583. if (substr($k, 0, 5) == 'HTTP_') {
    7584. -
    7585. $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
    7586. -
    7587. } else {
    7588. -
    7589. $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
    7590. -
    7591. }
    7592. -
    7593. if ($k == 'soapaction') {
    7594. -
    7595. // get SOAPAction header
    7596. -
    7597. $k = 'SOAPAction';
    7598. -
    7599. $v = str_replace('"', '', $v);
    7600. -
    7601. $v = str_replace('\\', '', $v);
    7602. -
    7603. $this->SOAPAction = $v;
    7604. -
    7605. } else if ($k == 'content-type') {
    7606. -
    7607. // get the character encoding of the incoming request
    7608. -
    7609. if (strpos($v, '=')) {
    7610. -
    7611. $enc = substr(strstr($v, '='), 1);
    7612. -
    7613. $enc = str_replace('"', '', $enc);
    7614. -
    7615. $enc = str_replace('\\', '', $enc);
    7616. -
    7617. if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
    7618. -
    7619. $this->xml_encoding = strtoupper($enc);
    7620. -
    7621. } else {
    7622. -
    7623. $this->xml_encoding = 'US-ASCII';
    7624. -
    7625. }
    7626. -
    7627. } else {
    7628. -
    7629. // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
    7630. -
    7631. $this->xml_encoding = 'ISO-8859-1';
    7632. -
    7633. }
    7634. -
    7635. }
    7636. -
    7637. $this->headers[$k] = $v;
    7638. -
    7639. $this->request .= "$k: $v\r\n";
    7640. -
    7641. $this->debug("$k: $v");
    7642. -
    7643. }
    7644. -
    7645. } elseif (is_array($HTTP_SERVER_VARS)) {
    7646. -
    7647. $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
    7648. -
    7649. foreach ($HTTP_SERVER_VARS as $k => $v) {
    7650. -
    7651. if (substr($k, 0, 5) == 'HTTP_') {
    7652. -
    7653. $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
    7654. -
    7655. } else {
    7656. -
    7657. $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
    7658. -
    7659. }
    7660. -
    7661. if ($k == 'soapaction') {
    7662. -
    7663. // get SOAPAction header
    7664. -
    7665. $k = 'SOAPAction';
    7666. -
    7667. $v = str_replace('"', '', $v);
    7668. -
    7669. $v = str_replace('\\', '', $v);
    7670. -
    7671. $this->SOAPAction = $v;
    7672. -
    7673. } else if ($k == 'content-type') {
    7674. -
    7675. // get the character encoding of the incoming request
    7676. -
    7677. if (strpos($v, '=')) {
    7678. -
    7679. $enc = substr(strstr($v, '='), 1);
    7680. -
    7681. $enc = str_replace('"', '', $enc);
    7682. -
    7683. $enc = str_replace('\\', '', $enc);
    7684. -
    7685. if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
    7686. -
    7687. $this->xml_encoding = strtoupper($enc);
    7688. -
    7689. } else {
    7690. -
    7691. $this->xml_encoding = 'US-ASCII';
    7692. -
    7693. }
    7694. -
    7695. } else {
    7696. -
    7697. // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
    7698. -
    7699. $this->xml_encoding = 'ISO-8859-1';
    7700. -
    7701. }
    7702. -
    7703. }
    7704. -
    7705. $this->headers[$k] = $v;
    7706. -
    7707. $this->request .= "$k: $v\r\n";
    7708. -
    7709. $this->debug("$k: $v");
    7710. -
    7711. }
    7712. -
    7713. } else {
    7714. -
    7715. $this->debug("In parse_http_headers, HTTP headers not accessible");
    7716. -
    7717. $this->setError("HTTP headers not accessible");
    7718. -
    7719. }
    7720. -
    7721. }
    7722. -
    7723.  
    7724. -
    7725. /**
    7726. -
    7727. * parses a request
    7728. -
    7729. *
    7730. -
    7731. * The following fields are set by this function (when successful)
    7732. -
    7733. *
    7734. -
    7735. * headers
    7736. -
    7737. * request
    7738. -
    7739. * xml_encoding
    7740. -
    7741. * SOAPAction
    7742. -
    7743. * request
    7744. -
    7745. * requestSOAP
    7746. -
    7747. * methodURI
    7748. -
    7749. * methodname
    7750. -
    7751. * methodparams
    7752. -
    7753. * requestHeaders
    7754. -
    7755. * document
    7756. -
    7757. *
    7758. -
    7759. * This sets the fault field on error
    7760. -
    7761. *
    7762. -
    7763. * @param string $data XML string
    7764. -
    7765. * @access private
    7766. -
    7767. */
    7768. -
    7769. function parse_request($data='') {
    7770. -
    7771. $this->debug('entering parse_request()');
    7772. -
    7773. $this->parse_http_headers();
    7774. -
    7775. $this->debug('got character encoding: '.$this->xml_encoding);
    7776. -
    7777. // uncompress if necessary
    7778. -
    7779. if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
    7780. -
    7781. $this->debug('got content encoding: ' . $this->headers['content-encoding']);
    7782. -
    7783. if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
    7784. -
    7785. // if decoding works, use it. else assume data wasn't gzencoded
    7786. -
    7787. if (function_exists('gzuncompress')) {
    7788. -
    7789. if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
    7790. -
    7791. $data = $degzdata;
    7792. -
    7793. } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
    7794. -
    7795. $data = $degzdata;
    7796. -
    7797. } else {
    7798. -
    7799. $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
    7800. -
    7801. return;
    7802. -
    7803. }
    7804. -
    7805. } else {
    7806. -
    7807. $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
    7808. -
    7809. return;
    7810. -
    7811. }
    7812. -
    7813. }
    7814. -
    7815. }
    7816. -
    7817. $this->request .= "\r\n".$data;
    7818. -
    7819. $data = $this->parseRequest($this->headers, $data);
    7820. -
    7821. $this->requestSOAP = $data;
    7822. -
    7823. $this->debug('leaving parse_request');
    7824. -
    7825. }
    7826. -
    7827.  
    7828. -
    7829. /**
    7830. -
    7831. * invokes a PHP function for the requested SOAP method
    7832. -
    7833. *
    7834. -
    7835. * The following fields are set by this function (when successful)
    7836. -
    7837. *
    7838. -
    7839. * methodreturn
    7840. -
    7841. *
    7842. -
    7843. * Note that the PHP function that is called may also set the following
    7844. -
    7845. * fields to affect the response sent to the client
    7846. -
    7847. *
    7848. -
    7849. * responseHeaders
    7850. -
    7851. * outgoing_headers
    7852. -
    7853. *
    7854. -
    7855. * This sets the fault field on error
    7856. -
    7857. *
    7858. -
    7859. * @access private
    7860. -
    7861. */
    7862. -
    7863. function invoke_method() {
    7864. -
    7865. $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
    7866. -
    7867.  
    7868. -
    7869. //
    7870. -
    7871. // if you are debugging in this area of the code, your service uses a class to implement methods,
    7872. -
    7873. // you use SOAP RPC, and the client is .NET, please be aware of the following...
    7874. -
    7875. // when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
    7876. -
    7877. // method name. that is fine for naming the .NET methods. it is not fine for properly constructing
    7878. -
    7879. // the XML request and reading the XML response. you need to add the RequestElementName and
    7880. -
    7881. // ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
    7882. -
    7883. // generates for the method. these parameters are used to specify the correct XML element names
    7884. -
    7885. // for .NET to use, i.e. the names with the '.' in them.
    7886. -
    7887. //
    7888. -
    7889. $orig_methodname = $this->methodname;
    7890. -
    7891. if ($this->wsdl) {
    7892. -
    7893. if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
    7894. -
    7895. $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
    7896. -
    7897. $this->appendDebug('opData=' . $this->varDump($this->opData));
    7898. -
    7899. } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
    7900. -
    7901. // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
    7902. -
    7903. $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
    7904. -
    7905. $this->appendDebug('opData=' . $this->varDump($this->opData));
    7906. -
    7907. $this->methodname = $this->opData['name'];
    7908. -
    7909. } else {
    7910. -
    7911. $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
    7912. -
    7913. $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
    7914. -
    7915. return;
    7916. -
    7917. }
    7918. -
    7919. } else {
    7920. -
    7921. $this->debug('in invoke_method, no WSDL to validate method');
    7922. -
    7923. }
    7924. -
    7925.  
    7926. -
    7927. // if a . is present in $this->methodname, we see if there is a class in scope,
    7928. -
    7929. // which could be referred to. We will also distinguish between two deliminators,
    7930. -
    7931. // to allow methods to be called a the class or an instance
    7932. -
    7933. if (strpos($this->methodname, '..') > 0) {
    7934. -
    7935. $delim = '..';
    7936. -
    7937. } else if (strpos($this->methodname, '.') > 0) {
    7938. -
    7939. $delim = '.';
    7940. -
    7941. } else {
    7942. -
    7943. $delim = '';
    7944. -
    7945. }
    7946. -
    7947. $this->debug("in invoke_method, delim=$delim");
    7948. -
    7949.  
    7950. -
    7951. $class = '';
    7952. -
    7953. $method = '';
    7954. -
    7955. if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
    7956. -
    7957. $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
    7958. -
    7959. if (class_exists($try_class)) {
    7960. -
    7961. // get the class and method name
    7962. -
    7963. $class = $try_class;
    7964. -
    7965. $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
    7966. -
    7967. $this->debug("in invoke_method, class=$class method=$method delim=$delim");
    7968. -
    7969. } else {
    7970. -
    7971. $this->debug("in invoke_method, class=$try_class not found");
    7972. -
    7973. }
    7974. -
    7975. } else {
    7976. -
    7977. $try_class = '';
    7978. -
    7979. $this->debug("in invoke_method, no class to try");
    7980. -
    7981. }
    7982. -
    7983.  
    7984. -
    7985. // does method exist?
    7986. -
    7987. if ($class == '') {
    7988. -
    7989. if (!function_exists($this->methodname)) {
    7990. -
    7991. $this->debug("in invoke_method, function '$this->methodname' not found!");
    7992. -
    7993. $this->result = 'fault: method not found';
    7994. -
    7995. $this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
    7996. -
    7997. return;
    7998. -
    7999. }
    8000. -
    8001. } else {
    8002. -
    8003. $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
    8004. -
    8005. if (!in_array($method_to_compare, get_class_methods($class))) {
    8006. -
    8007. $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
    8008. -
    8009. $this->result = 'fault: method not found';
    8010. -
    8011. $this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
    8012. -
    8013. return;
    8014. -
    8015. }
    8016. -
    8017. }
    8018. -
    8019.  
    8020. -
    8021. // evaluate message, getting back parameters
    8022. -
    8023. // verify that request parameters match the method's signature
    8024. -
    8025. if(! $this->verify_method($this->methodname,$this->methodparams)){
    8026. -
    8027. // debug
    8028. -
    8029. $this->debug('ERROR: request not verified against method signature');
    8030. -
    8031. $this->result = 'fault: request failed validation against method signature';
    8032. -
    8033. // return fault
    8034. -
    8035. $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
    8036. -
    8037. return;
    8038. -
    8039. }
    8040. -
    8041.  
    8042. -
    8043. // if there are parameters to pass
    8044. -
    8045. $this->debug('in invoke_method, params:');
    8046. -
    8047. $this->appendDebug($this->varDump($this->methodparams));
    8048. -
    8049. $this->debug("in invoke_method, calling '$this->methodname'");
    8050. -
    8051. if (!function_exists('call_user_func_array')) {
    8052. -
    8053. if ($class == '') {
    8054. -
    8055. $this->debug('in invoke_method, calling function using eval()');
    8056. -
    8057. $funcCall = "\$this->methodreturn = $this->methodname(";
    8058. -
    8059. } else {
    8060. -
    8061. if ($delim == '..') {
    8062. -
    8063. $this->debug('in invoke_method, calling class method using eval()');
    8064. -
    8065. $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
    8066. -
    8067. } else {
    8068. -
    8069. $this->debug('in invoke_method, calling instance method using eval()');
    8070. -
    8071. // generate unique instance name
    8072. -
    8073. $instname = "\$inst_".time();
    8074. -
    8075. $funcCall = $instname." = new ".$class."(); ";
    8076. -
    8077. $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
    8078. -
    8079. }
    8080. -
    8081. }
    8082. -
    8083. if ($this->methodparams) {
    8084. -
    8085. foreach ($this->methodparams as $param) {
    8086. -
    8087. if (is_array($param) || is_object($param)) {
    8088. -
    8089. $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
    8090. -
    8091. return;
    8092. -
    8093. }
    8094. -
    8095. $funcCall .= "\"$param\",";
    8096. -
    8097. }
    8098. -
    8099. $funcCall = substr($funcCall, 0, -1);
    8100. -
    8101. }
    8102. -
    8103. $funcCall .= ');';
    8104. -
    8105. $this->debug('in invoke_method, function call: '.$funcCall);
    8106. -
    8107. @eval($funcCall);
    8108. -
    8109. } else {
    8110. -
    8111. if ($class == '') {
    8112. -
    8113. $this->debug('in invoke_method, calling function using call_user_func_array()');
    8114. -
    8115. $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
    8116. -
    8117. } elseif ($delim == '..') {
    8118. -
    8119. $this->debug('in invoke_method, calling class method using call_user_func_array()');
    8120. -
    8121. $call_arg = array ($class, $method);
    8122. -
    8123. } else {
    8124. -
    8125. $this->debug('in invoke_method, calling instance method using call_user_func_array()');
    8126. -
    8127. $instance = new $class ();
    8128. -
    8129. $call_arg = array(&$instance, $method);
    8130. -
    8131. }
    8132. -
    8133. if (is_array($this->methodparams)) {
    8134. -
    8135. $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
    8136. -
    8137. } else {
    8138. -
    8139. $this->methodreturn = call_user_func_array($call_arg, array());
    8140. -
    8141. }
    8142. -
    8143. }
    8144. -
    8145. $this->debug('in invoke_method, methodreturn:');
    8146. -
    8147. $this->appendDebug($this->varDump($this->methodreturn));
    8148. -
    8149. $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
    8150. -
    8151. }
    8152. -
    8153.  
    8154. -
    8155. /**
    8156. -
    8157. * serializes the return value from a PHP function into a full SOAP Envelope
    8158. -
    8159. *
    8160. -
    8161. * The following fields are set by this function (when successful)
    8162. -
    8163. *
    8164. -
    8165. * responseSOAP
    8166. -
    8167. *
    8168. -
    8169. * This sets the fault field on error
    8170. -
    8171. *
    8172. -
    8173. * @access private
    8174. -
    8175. */
    8176. -
    8177. function serialize_return() {
    8178. -
    8179. $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
    8180. -
    8181. // if fault
    8182. -
    8183. if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
    8184. -
    8185. $this->debug('got a fault object from method');
    8186. -
    8187. $this->fault = $this->methodreturn;
    8188. -
    8189. return;
    8190. -
    8191. } elseif ($this->methodreturnisliteralxml) {
    8192. -
    8193. $return_val = $this->methodreturn;
    8194. -
    8195. // returned value(s)
    8196. -
    8197. } else {
    8198. -
    8199. $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
    8200. -
    8201. $this->debug('serializing return value');
    8202. -
    8203. if($this->wsdl){
    8204. -
    8205. if (sizeof($this->opData['output']['parts']) > 1) {
    8206. -
    8207. $this->debug('more than one output part, so use the method return unchanged');
    8208. -
    8209. $opParams = $this->methodreturn;
    8210. -
    8211. } elseif (sizeof($this->opData['output']['parts']) == 1) {
    8212. -
    8213. $this->debug('exactly one output part, so wrap the method return in a simple array');
    8214. -
    8215. // TODO: verify that it is not already wrapped!
    8216. -
    8217. //foreach ($this->opData['output']['parts'] as $name => $type) {
    8218. -
    8219. // $this->debug('wrap in element named ' . $name);
    8220. -
    8221. //}
    8222. -
    8223. $opParams = array($this->methodreturn);
    8224. -
    8225. }
    8226. -
    8227. $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
    8228. -
    8229. $this->appendDebug($this->wsdl->getDebug());
    8230. -
    8231. $this->wsdl->clearDebug();
    8232. -
    8233. if($errstr = $this->wsdl->getError()){
    8234. -
    8235. $this->debug('got wsdl error: '.$errstr);
    8236. -
    8237. $this->fault('SOAP-ENV:Server', 'unable to serialize result');
    8238. -
    8239. return;
    8240. -
    8241. }
    8242. -
    8243. } else {
    8244. -
    8245. if (isset($this->methodreturn)) {
    8246. -
    8247. $return_val = $this->serialize_val($this->methodreturn, 'return');
    8248. -
    8249. } else {
    8250. -
    8251. $return_val = '';
    8252. -
    8253. $this->debug('in absence of WSDL, assume void return for backward compatibility');
    8254. -
    8255. }
    8256. -
    8257. }
    8258. -
    8259. }
    8260. -
    8261. $this->debug('return value:');
    8262. -
    8263. $this->appendDebug($this->varDump($return_val));
    8264. -
    8265.  
    8266. -
    8267. $this->debug('serializing response');
    8268. -
    8269. if ($this->wsdl) {
    8270. -
    8271. $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
    8272. -
    8273. if ($this->opData['style'] == 'rpc') {
    8274. -
    8275. $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
    8276. -
    8277. if ($this->opData['output']['use'] == 'literal') {
    8278. -
    8279. // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace
    8280. -
    8281. if ($this->methodURI) {
    8282. -
    8283. $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
    8284. -
    8285. } else {
    8286. -
    8287. $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
    8288. -
    8289. }
    8290. -
    8291. } else {
    8292. -
    8293. if ($this->methodURI) {
    8294. -
    8295. $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
    8296. -
    8297. } else {
    8298. -
    8299. $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
    8300. -
    8301. }
    8302. -
    8303. }
    8304. -
    8305. } else {
    8306. -
    8307. $this->debug('style is not rpc for serialization: assume document');
    8308. -
    8309. $payload = $return_val;
    8310. -
    8311. }
    8312. -
    8313. } else {
    8314. -
    8315. $this->debug('do not have WSDL for serialization: assume rpc/encoded');
    8316. -
    8317. $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
    8318. -
    8319. }
    8320. -
    8321. $this->result = 'successful';
    8322. -
    8323. if($this->wsdl){
    8324. -
    8325. //if($this->debug_flag){
    8326. -
    8327. $this->appendDebug($this->wsdl->getDebug());
    8328. -
    8329. // }
    8330. -
    8331. if (isset($this->opData['output']['encodingStyle'])) {
    8332. -
    8333. $encodingStyle = $this->opData['output']['encodingStyle'];
    8334. -
    8335. } else {
    8336. -
    8337. $encodingStyle = '';
    8338. -
    8339. }
    8340. -
    8341. // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
    8342. -
    8343. $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
    8344. -
    8345. } else {
    8346. -
    8347. $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
    8348. -
    8349. }
    8350. -
    8351. $this->debug("Leaving serialize_return");
    8352. -
    8353. }
    8354. -
    8355.  
    8356. -
    8357. /**
    8358. -
    8359. * sends an HTTP response
    8360. -
    8361. *
    8362. -
    8363. * The following fields are set by this function (when successful)
    8364. -
    8365. *
    8366. -
    8367. * outgoing_headers
    8368. -
    8369. * response
    8370. -
    8371. *
    8372. -
    8373. * @access private
    8374. -
    8375. */
    8376. -
    8377. function send_response() {
    8378. -
    8379. $this->debug('Enter send_response');
    8380. -
    8381. if ($this->fault) {
    8382. -
    8383. $payload = $this->fault->serialize();
    8384. -
    8385. $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
    8386. -
    8387. $this->outgoing_headers[] = "Status: 500 Internal Server Error";
    8388. -
    8389. } else {
    8390. -
    8391. $payload = $this->responseSOAP;
    8392. -
    8393. // Some combinations of PHP+Web server allow the Status
    8394. -
    8395. // to come through as a header. Since OK is the default
    8396. -
    8397. // just do nothing.
    8398. -
    8399. // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
    8400. -
    8401. // $this->outgoing_headers[] = "Status: 200 OK";
    8402. -
    8403. }
    8404. -
    8405. // add debug data if in debug mode
    8406. -
    8407. if(isset($this->debug_flag) && $this->debug_flag){
    8408. -
    8409. $payload .= $this->getDebugAsXMLComment();
    8410. -
    8411. }
    8412. -
    8413. $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
    8414. -
    8415. preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
    8416. -
    8417. $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
    8418. -
    8419. // Let the Web server decide about this
    8420. -
    8421. //$this->outgoing_headers[] = "Connection: Close\r\n";
    8422. -
    8423. $payload = $this->getHTTPBody($payload);
    8424. -
    8425. $type = $this->getHTTPContentType();
    8426. -
    8427. $charset = $this->getHTTPContentTypeCharset();
    8428. -
    8429. $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
    8430. -
    8431. //begin code to compress payload - by John
    8432. -
    8433. // NOTE: there is no way to know whether the Web server will also compress
    8434. -
    8435. // this data.
    8436. -
    8437. if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
    8438. -
    8439. if (strstr($this->headers['accept-encoding'], 'gzip')) {
    8440. -
    8441. if (function_exists('gzencode')) {
    8442. -
    8443. if (isset($this->debug_flag) && $this->debug_flag) {
    8444. -
    8445. $payload .= "<!-- Content being gzipped -->";
    8446. -
    8447. }
    8448. -
    8449. $this->outgoing_headers[] = "Content-Encoding: gzip";
    8450. -
    8451. $payload = gzencode($payload);
    8452. -
    8453. } else {
    8454. -
    8455. if (isset($this->debug_flag) && $this->debug_flag) {
    8456. -
    8457. $payload .= "<!-- Content will not be gzipped: no gzencode -->";
    8458. -
    8459. }
    8460. -
    8461. }
    8462. -
    8463. } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
    8464. -
    8465. // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
    8466. -
    8467. // instead of gzcompress output,
    8468. -
    8469. // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
    8470. -
    8471. if (function_exists('gzdeflate')) {
    8472. -
    8473. if (isset($this->debug_flag) && $this->debug_flag) {
    8474. -
    8475. $payload .= "<!-- Content being deflated -->";
    8476. -
    8477. }
    8478. -
    8479. $this->outgoing_headers[] = "Content-Encoding: deflate";
    8480. -
    8481. $payload = gzdeflate($payload);
    8482. -
    8483. } else {
    8484. -
    8485. if (isset($this->debug_flag) && $this->debug_flag) {
    8486. -
    8487. $payload .= "<!-- Content will not be deflated: no gzcompress -->";
    8488. -
    8489. }
    8490. -
    8491. }
    8492. -
    8493. }
    8494. -
    8495. }
    8496. -
    8497. //end code
    8498. -
    8499. $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
    8500. -
    8501. reset($this->outgoing_headers);
    8502. -
    8503. foreach($this->outgoing_headers as $hdr){
    8504. -
    8505. header($hdr, false);
    8506. -
    8507. }
    8508. -
    8509. print $payload;
    8510. -
    8511. $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
    8512. -
    8513. }
    8514. -
    8515.  
    8516. -
    8517. /**
    8518. -
    8519. * takes the value that was created by parsing the request
    8520. -
    8521. * and compares to the method's signature, if available.
    8522. -
    8523. *
    8524. -
    8525. * @param string $operation The operation to be invoked
    8526. -
    8527. * @param array $request The array of parameter values
    8528. -
    8529. * @return boolean Whether the operation was found
    8530. -
    8531. * @access private
    8532. -
    8533. */
    8534. -
    8535. function verify_method($operation,$request){
    8536. -
    8537. if(isset($this->wsdl) && is_object($this->wsdl)){
    8538. -
    8539. if($this->wsdl->getOperationData($operation)){
    8540. -
    8541. return true;
    8542. -
    8543. }
    8544. -
    8545. } elseif(isset($this->operations[$operation])){
    8546. -
    8547. return true;
    8548. -
    8549. }
    8550. -
    8551. return false;
    8552. -
    8553. }
    8554. -
    8555.  
    8556. -
    8557. /**
    8558. -
    8559. * processes SOAP message received from client
    8560. -
    8561. *
    8562. -
    8563. * @param array $headers The HTTP headers
    8564. -
    8565. * @param string $data unprocessed request data from client
    8566. -
    8567. * @return mixed value of the message, decoded into a PHP type
    8568. -
    8569. * @access private
    8570. -
    8571. */
    8572. -
    8573. function parseRequest($headers, $data) {
    8574. -
    8575. $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
    8576. -
    8577. $this->appendDebug($this->varDump($headers));
    8578. -
    8579. if (!isset($headers['content-type'])) {
    8580. -
    8581. $this->setError('Request not of type text/xml (no content-type header)');
    8582. -
    8583. return false;
    8584. -
    8585. }
    8586. -
    8587. if (!strstr($headers['content-type'], 'text/xml')) {
    8588. -
    8589. $this->setError('Request not of type text/xml');
    8590. -
    8591. return false;
    8592. -
    8593. }
    8594. -
    8595. if (strpos($headers['content-type'], '=')) {
    8596. -
    8597. $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
    8598. -
    8599. $this->debug('Got response encoding: ' . $enc);
    8600. -
    8601. if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
    8602. -
    8603. $this->xml_encoding = strtoupper($enc);
    8604. -
    8605. } else {
    8606. -
    8607. $this->xml_encoding = 'US-ASCII';
    8608. -
    8609. }
    8610. -
    8611. } else {
    8612. -
    8613. // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
    8614. -
    8615. $this->xml_encoding = 'ISO-8859-1';
    8616. -
    8617. }
    8618. -
    8619. $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
    8620. -
    8621. // parse response, get soap parser obj
    8622. -
    8623. $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
    8624. -
    8625. // parser debug
    8626. -
    8627. $this->debug("parser debug: \n".$parser->getDebug());
    8628. -
    8629. // if fault occurred during message parsing
    8630. -
    8631. if($err = $parser->getError()){
    8632. -
    8633. $this->result = 'fault: error in msg parsing: '.$err;
    8634. -
    8635. $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
    8636. -
    8637. // else successfully parsed request into soapval object
    8638. -
    8639. } else {
    8640. -
    8641. // get/set methodname
    8642. -
    8643. $this->methodURI = $parser->root_struct_namespace;
    8644. -
    8645. $this->methodname = $parser->root_struct_name;
    8646. -
    8647. $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
    8648. -
    8649. $this->debug('calling parser->get_soapbody()');
    8650. -
    8651. $this->methodparams = $parser->get_soapbody();
    8652. -
    8653. // get SOAP headers
    8654. -
    8655. $this->requestHeaders = $parser->getHeaders();
    8656. -
    8657. // get SOAP Header
    8658. -
    8659. $this->requestHeader = $parser->get_soapheader();
    8660. -
    8661. // add document for doclit support
    8662. -
    8663. $this->document = $parser->document;
    8664. -
    8665. }
    8666. -
    8667. }
    8668. -
    8669.  
    8670. -
    8671. /**
    8672. -
    8673. * gets the HTTP body for the current response.
    8674. -
    8675. *
    8676. -
    8677. * @param string $soapmsg The SOAP payload
    8678. -
    8679. * @return string The HTTP body, which includes the SOAP payload
    8680. -
    8681. * @access private
    8682. -
    8683. */
    8684. -
    8685. function getHTTPBody($soapmsg) {
    8686. -
    8687. return $soapmsg;
    8688. -
    8689. }
    8690. -
    8691. -
    8692. /**
    8693. -
    8694. * gets the HTTP content type for the current response.
    8695. -
    8696. *
    8697. -
    8698. * Note: getHTTPBody must be called before this.
    8699. -
    8700. *
    8701. -
    8702. * @return string the HTTP content type for the current response.
    8703. -
    8704. * @access private
    8705. -
    8706. */
    8707. -
    8708. function getHTTPContentType() {
    8709. -
    8710. return 'text/xml';
    8711. -
    8712. }
    8713. -
    8714. -
    8715. /**
    8716. -
    8717. * gets the HTTP content type charset for the current response.
    8718. -
    8719. * returns false for non-text content types.
    8720. -
    8721. *
    8722. -
    8723. * Note: getHTTPBody must be called before this.
    8724. -
    8725. *
    8726. -
    8727. * @return string the HTTP content type charset for the current response.
    8728. -
    8729. * @access private
    8730. -
    8731. */
    8732. -
    8733. function getHTTPContentTypeCharset() {
    8734. -
    8735. return $this->soap_defencoding;
    8736. -
    8737. }
    8738. -
    8739.  
    8740. -
    8741. /**
    8742. -
    8743. * add a method to the dispatch map (this has been replaced by the register method)
    8744. -
    8745. *
    8746. -
    8747. * @param string $methodname
    8748. -
    8749. * @param string $in array of input values
    8750. -
    8751. * @param string $out array of output values
    8752. -
    8753. * @access public
    8754. -
    8755. * @deprecated
    8756. -
    8757. */
    8758. -
    8759. function add_to_map($methodname,$in,$out){
    8760. -
    8761. $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
    8762. -
    8763. }
    8764. -
    8765.  
    8766. -
    8767. /**
    8768. -
    8769. * register a service function with the server
    8770. -
    8771. *
    8772. -
    8773. * @param string $name the name of the PHP function, class.method or class..method
    8774. -
    8775. * @param array $in assoc array of input values: key = param name, value = param type
    8776. -
    8777. * @param array $out assoc array of output values: key = param name, value = param type
    8778. -
    8779. * @param mixed $namespace the element namespace for the method or false
    8780. -
    8781. * @param mixed $soapaction the soapaction for the method or false
    8782. -
    8783. * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
    8784. -
    8785. * @param mixed $use optional (encoded|literal) or false
    8786. -
    8787. * @param string $documentation optional Description to include in WSDL
    8788. -
    8789. * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
    8790. -
    8791. * @access public
    8792. -
    8793. */
    8794. -
    8795. function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
    8796. -
    8797. global $HTTP_SERVER_VARS;
    8798. -
    8799.  
    8800. -
    8801. if($this->externalWSDLURL){
    8802. -
    8803. die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
    8804. -
    8805. }
    8806. -
    8807. if (! $name) {
    8808. -
    8809. die('You must specify a name when you register an operation');
    8810. -
    8811. }
    8812. -
    8813. if (!is_array($in)) {
    8814. -
    8815. die('You must provide an array for operation inputs');
    8816. -
    8817. }
    8818. -
    8819. if (!is_array($out)) {
    8820. -
    8821. die('You must provide an array for operation outputs');
    8822. -
    8823. }
    8824. -
    8825. if(false == $namespace) {
    8826. -
    8827. }
    8828. -
    8829. if(false == $soapaction) {
    8830. -
    8831. if (isset($_SERVER)) {
    8832. -
    8833. $SERVER_NAME = $_SERVER['SERVER_NAME'];
    8834. -
    8835. $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
    8836. -
    8837. $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
    8838. -
    8839. } elseif (isset($HTTP_SERVER_VARS)) {
    8840. -
    8841. $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
    8842. -
    8843. $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
    8844. -
    8845. $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
    8846. -
    8847. } else {
    8848. -
    8849. $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
    8850. -
    8851. }
    8852. -
    8853. if ($HTTPS == '1' || $HTTPS == 'on') {
    8854. -
    8855. $SCHEME = 'https';
    8856. -
    8857. } else {
    8858. -
    8859. $SCHEME = 'http';
    8860. -
    8861. }
    8862. -
    8863. $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
    8864. -
    8865. }
    8866. -
    8867. if(false == $style) {
    8868. -
    8869. $style = "rpc";
    8870. -
    8871. }
    8872. -
    8873. if(false == $use) {
    8874. -
    8875. $use = "encoded";
    8876. -
    8877. }
    8878. -
    8879. if ($use == 'encoded' && $encodingStyle == '') {
    8880. -
    8881. $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
    8882. -
    8883. }
    8884. -
    8885.  
    8886. -
    8887. $this->operations[$name] = array(
    8888. -
    8889. 'name' => $name,
    8890. -
    8891. 'in' => $in,
    8892. -
    8893. 'out' => $out,
    8894. -
    8895. 'namespace' => $namespace,
    8896. -
    8897. 'soapaction' => $soapaction,
    8898. -
    8899. 'style' => $style);
    8900. -
    8901. if($this->wsdl){
    8902. -
    8903. $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
    8904. -
    8905. }
    8906. -
    8907. return true;
    8908. -
    8909. }
    8910. -
    8911.  
    8912. -
    8913. /**
    8914. -
    8915. * Specify a fault to be returned to the client.
    8916. -
    8917. * This also acts as a flag to the server that a fault has occured.
    8918. -
    8919. *
    8920. -
    8921. * @param string $faultcode
    8922. -
    8923. * @param string $faultstring
    8924. -
    8925. * @param string $faultactor
    8926. -
    8927. * @param string $faultdetail
    8928. -
    8929. * @access public
    8930. -
    8931. */
    8932. -
    8933. function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
    8934. -
    8935. if ($faultdetail == '' && $this->debug_flag) {
    8936. -
    8937. $faultdetail = $this->getDebug();
    8938. -
    8939. }
    8940. -
    8941. $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
    8942. -
    8943. $this->fault->soap_defencoding = $this->soap_defencoding;
    8944. -
    8945. }
    8946. -
    8947.  
    8948. -
    8949. /**
    8950. -
    8951. * Sets up wsdl object.
    8952. -
    8953. * Acts as a flag to enable internal WSDL generation
    8954. -
    8955. *
    8956. -
    8957. * @param string $serviceName, name of the service
    8958. -
    8959. * @param mixed $namespace optional 'tns' service namespace or false
    8960. -
    8961. * @param mixed $endpoint optional URL of service endpoint or false
    8962. -
    8963. * @param string $style optional (rpc|document) WSDL style (also specified by operation)
    8964. -
    8965. * @param string $transport optional SOAP transport
    8966. -
    8967. * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
    8968. -
    8969. */
    8970. -
    8971. function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
    8972. -
    8973. {
    8974. -
    8975. global $HTTP_SERVER_VARS;
    8976. -
    8977.  
    8978. -
    8979. if (isset($_SERVER)) {
    8980. -
    8981. $SERVER_NAME = $_SERVER['SERVER_NAME'];
    8982. -
    8983. $SERVER_PORT = $_SERVER['SERVER_PORT'];
    8984. -
    8985. $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
    8986. -
    8987. $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
    8988. -
    8989. } elseif (isset($HTTP_SERVER_VARS)) {
    8990. -
    8991. $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
    8992. -
    8993. $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
    8994. -
    8995. $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
    8996. -
    8997. $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
    8998. -
    8999. } else {
    9000. -
    9001. $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
    9002. -
    9003. }
    9004. -
    9005. // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
    9006. -
    9007. $colon = strpos($SERVER_NAME,":");
    9008. -
    9009. if ($colon) {
    9010. -
    9011. $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
    9012. -
    9013. }
    9014. -
    9015. if ($SERVER_PORT == 80) {
    9016. -
    9017. $SERVER_PORT = '';
    9018. -
    9019. } else {
    9020. -
    9021. $SERVER_PORT = ':' . $SERVER_PORT;
    9022. -
    9023. }
    9024. -
    9025. if(false == $namespace) {
    9026. -
    9027. $namespace = "http://$SERVER_NAME/soap/$serviceName";
    9028. -
    9029. }
    9030. -
    9031. -
    9032. if(false == $endpoint) {
    9033. -
    9034. if ($HTTPS == '1' || $HTTPS == 'on') {
    9035. -
    9036. $SCHEME = 'https';
    9037. -
    9038. } else {
    9039. -
    9040. $SCHEME = 'http';
    9041. -
    9042. }
    9043. -
    9044. $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
    9045. -
    9046. }
    9047. -
    9048. -
    9049. if(false == $schemaTargetNamespace) {
    9050. -
    9051. $schemaTargetNamespace = $namespace;
    9052. -
    9053. }
    9054. -
    9055. -
    9056. $this->wsdl = new wsdl;
    9057. -
    9058. $this->wsdl->serviceName = $serviceName;
    9059. -
    9060. $this->wsdl->endpoint = $endpoint;
    9061. -
    9062. $this->wsdl->namespaces['tns'] = $namespace;
    9063. -
    9064. $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
    9065. -
    9066. $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
    9067. -
    9068. if ($schemaTargetNamespace != $namespace) {
    9069. -
    9070. $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
    9071. -
    9072. }
    9073. -
    9074. $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
    9075. -
    9076. if ($style == 'document') {
    9077. -
    9078. $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
    9079. -
    9080. }
    9081. -
    9082. $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
    9083. -
    9084. $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
    9085. -
    9086. $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
    9087. -
    9088. $this->wsdl->bindings[$serviceName.'Binding'] = array(
    9089. -
    9090. 'name'=>$serviceName.'Binding',
    9091. -
    9092. 'style'=>$style,
    9093. -
    9094. 'transport'=>$transport,
    9095. -
    9096. 'portType'=>$serviceName.'PortType');
    9097. -
    9098. $this->wsdl->ports[$serviceName.'Port'] = array(
    9099. -
    9100. 'binding'=>$serviceName.'Binding',
    9101. -
    9102. 'location'=>$endpoint,
    9103. -
    9104. 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
    9105. -
    9106. }
    9107. -
    9108. }
    9109. -
    9110.  
    9111. -
    9112. /**
    9113. -
    9114. * Backward compatibility
    9115. -
    9116. */
    9117. -
    9118. class soap_server extends nusoap_server {
    9119. -
    9120. }
    9121. -
    9122.  
    9123. -
    9124. ?><?php
    9125. -
    9126.  
    9127. -
    9128.  
    9129. -
    9130.  
    9131. -
    9132. /**
    9133. -
    9134. * parses a WSDL file, allows access to it's data, other utility methods.
    9135. -
    9136. * also builds WSDL structures programmatically.
    9137. -
    9138. *
    9139. -
    9140. * @author Dietrich Ayala <dietrich@ganx4.com>
    9141. -
    9142. * @author Scott Nichol <snichol@users.sourceforge.net>
    9143. -
    9144. * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    9145. -
    9146. * @access public
    9147. -
    9148. */
    9149. -
    9150. class wsdl extends nusoap_base {
    9151. -
    9152. // URL or filename of the root of this WSDL
    9153. -
    9154. -
    9155. var $wsdl;
    9156. -
    9157. // define internal arrays of bindings, ports, operations, messages, etc.
    9158. -
    9159. -
    9160. var $schemas = array();
    9161. -
    9162. var $currentSchema;
    9163. -
    9164. var $message = array();
    9165. -
    9166. var $complexTypes = array();
    9167. -
    9168. var $messages = array();
    9169. -
    9170. var $currentMessage;
    9171. -
    9172. var $currentOperation;
    9173. -
    9174. var $portTypes = array();
    9175. -
    9176. var $currentPortType;
    9177. -
    9178. var $bindings = array();
    9179. -
    9180. var $currentBinding;
    9181. -
    9182. var $ports = array();
    9183. -
    9184. var $currentPort;
    9185. -
    9186. var $opData = array();
    9187. -
    9188. var $status = '';
    9189. -
    9190. var $documentation = false;
    9191. -
    9192. var $endpoint = '';
    9193. -
    9194. // array of wsdl docs to import
    9195. -
    9196. -
    9197. var $import = array();
    9198. -
    9199. // parser vars
    9200. -
    9201. -
    9202. var $parser;
    9203. -
    9204. var $position = 0;
    9205. -
    9206. var $depth = 0;
    9207. -
    9208. var $depth_array = array();
    9209. -
    9210. // for getting wsdl
    9211. -
    9212. -
    9213. var $proxyhost = '';
    9214. -
    9215. var $proxyport = '';
    9216. -
    9217. var $proxyusername = '';
    9218. -
    9219. var $proxypassword = '';
    9220. -
    9221. var $timeout = 0;
    9222. -
    9223. var $response_timeout = 30;
    9224. -
    9225. var $curl_options = array(); // User-specified cURL options
    9226. -
    9227. -
    9228. var $use_curl = false; // whether to always try to use cURL
    9229. -
    9230. // for HTTP authentication
    9231. -
    9232. -
    9233. var $username = ''; // Username for HTTP authentication
    9234. -
    9235. -
    9236. var $password = ''; // Password for HTTP authentication
    9237. -
    9238. -
    9239. var $authtype = ''; // Type of HTTP authentication
    9240. -
    9241. -
    9242. var $certRequest = array(); // Certificate for HTTP SSL authentication
    9243. -
    9244.  
    9245. -
    9246. -
    9247.  
    9248. -
    9249. /**
    9250. -
    9251. * constructor
    9252. -
    9253. *
    9254. -
    9255. * @param string $wsdl WSDL document URL
    9256. -
    9257. * @param string $proxyhost
    9258. -
    9259. * @param string $proxyport
    9260. -
    9261. * @param string $proxyusername
    9262. -
    9263. * @param string $proxypassword
    9264. -
    9265. * @param integer $timeout set the connection timeout
    9266. -
    9267. * @param integer $response_timeout set the response timeout
    9268. -
    9269. * @param array $curl_options user-specified cURL options
    9270. -
    9271. * @param boolean $use_curl try to use cURL
    9272. -
    9273. * @access public
    9274. -
    9275. */
    9276. -
    9277. function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
    9278. -
    9279. parent::nusoap_base();
    9280. -
    9281. $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
    9282. -
    9283. $this->proxyhost = $proxyhost;
    9284. -
    9285. $this->proxyport = $proxyport;
    9286. -
    9287. $this->proxyusername = $proxyusername;
    9288. -
    9289. $this->proxypassword = $proxypassword;
    9290. -
    9291. $this->timeout = $timeout;
    9292. -
    9293. $this->response_timeout = $response_timeout;
    9294. -
    9295. if (is_array($curl_options))
    9296. -
    9297. $this->curl_options = $curl_options;
    9298. -
    9299. $this->use_curl = $use_curl;
    9300. -
    9301. $this->fetchWSDL($wsdl);
    9302. -
    9303. }
    9304. -
    9305.  
    9306. -
    9307. /**
    9308. -
    9309. * fetches the WSDL document and parses it
    9310. -
    9311. *
    9312. -
    9313. * @access public
    9314. -
    9315. */
    9316. -
    9317. function fetchWSDL($wsdl) {
    9318. -
    9319. $this->debug("parse and process WSDL path=$wsdl");
    9320. -
    9321. $this->wsdl = $wsdl;
    9322. -
    9323. // parse wsdl file
    9324. -
    9325. if ($this->wsdl != "") {
    9326. -
    9327. $this->parseWSDL($this->wsdl);
    9328. -
    9329. }
    9330. -
    9331. // imports
    9332. -
    9333. // TODO: handle imports more properly, grabbing them in-line and nesting them
    9334. -
    9335. $imported_urls = array();
    9336. -
    9337. $imported = 1;
    9338. -
    9339. while ($imported > 0) {
    9340. -
    9341. $imported = 0;
    9342. -
    9343. // Schema imports
    9344. -
    9345. foreach ($this->schemas as $ns => $list) {
    9346. -
    9347. foreach ($list as $xs) {
    9348. -
    9349. $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
    9350. -
    9351. foreach ($xs->imports as $ns2 => $list2) {
    9352. -
    9353. for ($ii = 0; $ii < count($list2); $ii++) {
    9354. -
    9355. if (! $list2[$ii]['loaded']) {
    9356. -
    9357. $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
    9358. -
    9359. $url = $list2[$ii]['location'];
    9360. -
    9361. if ($url != '') {
    9362. -
    9363. $urlparts = parse_url($url);
    9364. -
    9365. if (!isset($urlparts['host'])) {
    9366. -
    9367. $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
    9368. -
    9369. substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
    9370. -
    9371. }
    9372. -
    9373. if (! in_array($url, $imported_urls)) {
    9374. -
    9375. $this->parseWSDL($url);
    9376. -
    9377. $imported++;
    9378. -
    9379. $imported_urls[] = $url;
    9380. -
    9381. }
    9382. -
    9383. } else {
    9384. -
    9385. $this->debug("Unexpected scenario: empty URL for unloaded import");
    9386. -
    9387. }
    9388. -
    9389. }
    9390. -
    9391. }
    9392. -
    9393. }
    9394. -
    9395. }
    9396. -
    9397. }
    9398. -
    9399. // WSDL imports
    9400. -
    9401. $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
    9402. -
    9403. foreach ($this->import as $ns => $list) {
    9404. -
    9405. for ($ii = 0; $ii < count($list); $ii++) {
    9406. -
    9407. if (! $list[$ii]['loaded']) {
    9408. -
    9409. $this->import[$ns][$ii]['loaded'] = true;
    9410. -
    9411. $url = $list[$ii]['location'];
    9412. -
    9413. if ($url != '') {
    9414. -
    9415. $urlparts = parse_url($url);
    9416. -
    9417. if (!isset($urlparts['host'])) {
    9418. -
    9419. $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
    9420. -
    9421. substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
    9422. -
    9423. }
    9424. -
    9425. if (! in_array($url, $imported_urls)) {
    9426. -
    9427. $this->parseWSDL($url);
    9428. -
    9429. $imported++;
    9430. -
    9431. $imported_urls[] = $url;
    9432. -
    9433. }
    9434. -
    9435. } else {
    9436. -
    9437. $this->debug("Unexpected scenario: empty URL for unloaded import");
    9438. -
    9439. }
    9440. -
    9441. }
    9442. -
    9443. }
    9444. -
    9445. }
    9446. -
    9447. }
    9448. -
    9449. // add new data to operation data
    9450. -
    9451. foreach($this->bindings as $binding => $bindingData) {
    9452. -
    9453. if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
    9454. -
    9455. foreach($bindingData['operations'] as $operation => $data) {
    9456. -
    9457. $this->debug('post-parse data gathering for ' . $operation);
    9458. -
    9459. $this->bindings[$binding]['operations'][$operation]['input'] =
    9460. -
    9461. isset($this->bindings[$binding]['operations'][$operation]['input']) ?
    9462. -
    9463. array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
    9464. -
    9465. $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
    9466. -
    9467. $this->bindings[$binding]['operations'][$operation]['output'] =
    9468. -
    9469. isset($this->bindings[$binding]['operations'][$operation]['output']) ?
    9470. -
    9471. array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
    9472. -
    9473. $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
    9474. -
    9475. if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
    9476. -
    9477. $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
    9478. -
    9479. }
    9480. -
    9481. if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
    9482. -
    9483. $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
    9484. -
    9485. }
    9486. -
    9487. // Set operation style if necessary, but do not override one already provided
    9488. -
    9489. if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
    9490. -
    9491. $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
    9492. -
    9493. }
    9494. -
    9495. $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
    9496. -
    9497. $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
    9498. -
    9499. $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
    9500. -
    9501. }
    9502. -
    9503. }
    9504. -
    9505. }
    9506. -
    9507. }
    9508. -
    9509.  
    9510. -
    9511. /**
    9512. -
    9513. * parses the wsdl document
    9514. -
    9515. *
    9516. -
    9517. * @param string $wsdl path or URL
    9518. -
    9519. * @access private
    9520. -
    9521. */
    9522. -
    9523. function parseWSDL($wsdl = '') {
    9524. -
    9525. $this->debug("parse WSDL at path=$wsdl");
    9526. -
    9527.  
    9528. -
    9529. if ($wsdl == '') {
    9530. -
    9531. $this->debug('no wsdl passed to parseWSDL()!!');
    9532. -
    9533. $this->setError('no wsdl passed to parseWSDL()!!');
    9534. -
    9535. return false;
    9536. -
    9537. }
    9538. -
    9539. -
    9540. // parse $wsdl for url format
    9541. -
    9542. $wsdl_props = parse_url($wsdl);
    9543. -
    9544.  
    9545. -
    9546. if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
    9547. -
    9548. $this->debug('getting WSDL http(s) URL ' . $wsdl);
    9549. -
    9550. // get wsdl
    9551. -
    9552. $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
    9553. -
    9554. $tr->request_method = 'GET';
    9555. -
    9556. $tr->useSOAPAction = false;
    9557. -
    9558. if($this->proxyhost && $this->proxyport){
    9559. -
    9560. $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
    9561. -
    9562. }
    9563. -
    9564. if ($this->authtype != '') {
    9565. -
    9566. $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
    9567. -
    9568. }
    9569. -
    9570. $tr->setEncoding('gzip, deflate');
    9571. -
    9572. $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
    9573. -
    9574. //$this->debug("WSDL request\n" . $tr->outgoing_payload);
    9575. -
    9576. //$this->debug("WSDL response\n" . $tr->incoming_payload);
    9577. -
    9578. $this->appendDebug($tr->getDebug());
    9579. -
    9580. // catch errors
    9581. -
    9582. if($err = $tr->getError() ){
    9583. -
    9584. $errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err;
    9585. -
    9586. $this->debug($errstr);
    9587. -
    9588. $this->setError($errstr);
    9589. -
    9590. unset($tr);
    9591. -
    9592. return false;
    9593. -
    9594. }
    9595. -
    9596. unset($tr);
    9597. -
    9598. $this->debug("got WSDL URL");
    9599. -
    9600. } else {
    9601. -
    9602. // $wsdl is not http(s), so treat it as a file URL or plain file path
    9603. -
    9604. if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
    9605. -
    9606. $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
    9607. -
    9608. } else {
    9609. -
    9610. $path = $wsdl;
    9611. -
    9612. }
    9613. -
    9614. $this->debug('getting WSDL file ' . $path);
    9615. -
    9616. if ($fp = @fopen($path, 'r')) {
    9617. -
    9618. $wsdl_string = '';
    9619. -
    9620. while ($data = fread($fp, 32768)) {
    9621. -
    9622. $wsdl_string .= $data;
    9623. -
    9624. }
    9625. -
    9626. fclose($fp);
    9627. -
    9628. } else {
    9629. -
    9630. $errstr = "Bad path to WSDL file $path";
    9631. -
    9632. $this->debug($errstr);
    9633. -
    9634. $this->setError($errstr);
    9635. -
    9636. return false;
    9637. -
    9638. }
    9639. -
    9640. }
    9641. -
    9642. $this->debug('Parse WSDL');
    9643. -
    9644. // end new code added
    9645. -
    9646. // Create an XML parser.
    9647. -
    9648. $this->parser = xml_parser_create();
    9649. -
    9650. // Set the options for parsing the XML data.
    9651. -
    9652. // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
    9653. -
    9654. xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
    9655. -
    9656. // Set the object for the parser.
    9657. -
    9658. xml_set_object($this->parser, $this);
    9659. -
    9660. // Set the element handlers for the parser.
    9661. -
    9662. xml_set_element_handler($this->parser, 'start_element', 'end_element');
    9663. -
    9664. xml_set_character_data_handler($this->parser, 'character_data');
    9665. -
    9666. // Parse the XML file.
    9667. -
    9668. if (!xml_parse($this->parser, $wsdl_string, true)) {
    9669. -
    9670. // Display an error message.
    9671. -
    9672. $errstr = sprintf(
    9673. -
    9674. 'XML error parsing WSDL from %s on line %d: %s',
    9675. -
    9676. $wsdl,
    9677. -
    9678. xml_get_current_line_number($this->parser),
    9679. -
    9680. xml_error_string(xml_get_error_code($this->parser))
    9681. -
    9682. );
    9683. -
    9684. $this->debug($errstr);
    9685. -
    9686. $this->debug("XML payload:\n" . $wsdl_string);
    9687. -
    9688. $this->setError($errstr);
    9689. -
    9690. return false;
    9691. -
    9692. }
    9693. -
    9694. // free the parser
    9695. -
    9696. xml_parser_free($this->parser);
    9697. -
    9698. $this->debug('Parsing WSDL done');
    9699. -
    9700. // catch wsdl parse errors
    9701. -
    9702. if($this->getError()){
    9703. -
    9704. return false;
    9705. -
    9706. }
    9707. -
    9708. return true;
    9709. -
    9710. }
    9711. -
    9712.  
    9713. -
    9714. /**
    9715. -
    9716. * start-element handler
    9717. -
    9718. *
    9719. -
    9720. * @param string $parser XML parser object
    9721. -
    9722. * @param string $name element name
    9723. -
    9724. * @param string $attrs associative array of attributes
    9725. -
    9726. * @access private
    9727. -
    9728. */
    9729. -
    9730. function start_element($parser, $name, $attrs)
    9731. -
    9732. {
    9733. -
    9734. if ($this->status == 'schema') {
    9735. -
    9736. $this->currentSchema->schemaStartElement($parser, $name, $attrs);
    9737. -
    9738. $this->appendDebug($this->currentSchema->getDebug());
    9739. -
    9740. $this->currentSchema->clearDebug();
    9741. -
    9742. } elseif (preg_match('/schema$/', $name)) {
    9743. -
    9744. $this->debug('Parsing WSDL schema');
    9745. -
    9746. // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
    9747. -
    9748. $this->status = 'schema';
    9749. -
    9750. $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
    9751. -
    9752. $this->currentSchema->schemaStartElement($parser, $name, $attrs);
    9753. -
    9754. $this->appendDebug($this->currentSchema->getDebug());
    9755. -
    9756. $this->currentSchema->clearDebug();
    9757. -
    9758. } else {
    9759. -
    9760. // position in the total number of elements, starting from 0
    9761. -
    9762. $pos = $this->position++;
    9763. -
    9764. $depth = $this->depth++;
    9765. -
    9766. // set self as current value for this depth
    9767. -
    9768. $this->depth_array[$depth] = $pos;
    9769. -
    9770. $this->message[$pos] = array('cdata' => '');
    9771. -
    9772. // process attributes
    9773. -
    9774. if (count($attrs) > 0) {
    9775. -
    9776. // register namespace declarations
    9777. -
    9778. foreach($attrs as $k => $v) {
    9779. -
    9780. if (preg_match('/^xmlns/',$k)) {
    9781. -
    9782. if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
    9783. -
    9784. $this->namespaces[$ns_prefix] = $v;
    9785. -
    9786. } else {
    9787. -
    9788. $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
    9789. -
    9790. }
    9791. -
    9792. if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
    9793. -
    9794. $this->XMLSchemaVersion = $v;
    9795. -
    9796. $this->namespaces['xsi'] = $v . '-instance';
    9797. -
    9798. }
    9799. -
    9800. }
    9801. -
    9802. }
    9803. -
    9804. // expand each attribute prefix to its namespace
    9805. -
    9806. foreach($attrs as $k => $v) {
    9807. -
    9808. $k = strpos($k, ':') ? $this->expandQname($k) : $k;
    9809. -
    9810. if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
    9811. -
    9812. $v = strpos($v, ':') ? $this->expandQname($v) : $v;
    9813. -
    9814. }
    9815. -
    9816. $eAttrs[$k] = $v;
    9817. -
    9818. }
    9819. -
    9820. $attrs = $eAttrs;
    9821. -
    9822. } else {
    9823. -
    9824. $attrs = array();
    9825. -
    9826. }
    9827. -
    9828. // get element prefix, namespace and name
    9829. -
    9830. if (preg_match('/:/', $name)) {
    9831. -
    9832. // get ns prefix
    9833. -
    9834. $prefix = substr($name, 0, strpos($name, ':'));
    9835. -
    9836. // get ns
    9837. -
    9838. $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
    9839. -
    9840. // get unqualified name
    9841. -
    9842. $name = substr(strstr($name, ':'), 1);
    9843. -
    9844. }
    9845. -
    9846. // process attributes, expanding any prefixes to namespaces
    9847. -
    9848. // find status, register data
    9849. -
    9850. switch ($this->status) {
    9851. -
    9852. case 'message':
    9853. -
    9854. if ($name == 'part') {
    9855. -
    9856. if (isset($attrs['type'])) {
    9857. -
    9858. $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
    9859. -
    9860. $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
    9861. -
    9862. }
    9863. -
    9864. if (isset($attrs['element'])) {
    9865. -
    9866. $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
    9867. -
    9868. $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
    9869. -
    9870. }
    9871. -
    9872. }
    9873. -
    9874. break;
    9875. -
    9876. case 'portType':
    9877. -
    9878. switch ($name) {
    9879. -
    9880. case 'operation':
    9881. -
    9882. $this->currentPortOperation = $attrs['name'];
    9883. -
    9884. $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
    9885. -
    9886. if (isset($attrs['parameterOrder'])) {
    9887. -
    9888. $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
    9889. -
    9890. }
    9891. -
    9892. break;
    9893. -
    9894. case 'documentation':
    9895. -
    9896. $this->documentation = true;
    9897. -
    9898. break;
    9899. -
    9900. // merge input/output data
    9901. -
    9902. default:
    9903. -
    9904. $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
    9905. -
    9906. $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
    9907. -
    9908. break;
    9909. -
    9910. }
    9911. -
    9912. break;
    9913. -
    9914. case 'binding':
    9915. -
    9916. switch ($name) {
    9917. -
    9918. case 'binding':
    9919. -
    9920. // get ns prefix
    9921. -
    9922. if (isset($attrs['style'])) {
    9923. -
    9924. $this->bindings[$this->currentBinding]['prefix'] = $prefix;
    9925. -
    9926. }
    9927. -
    9928. $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
    9929. -
    9930. break;
    9931. -
    9932. case 'header':
    9933. -
    9934. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
    9935. -
    9936. break;
    9937. -
    9938. case 'operation':
    9939. -
    9940. if (isset($attrs['soapAction'])) {
    9941. -
    9942. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
    9943. -
    9944. }
    9945. -
    9946. if (isset($attrs['style'])) {
    9947. -
    9948. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
    9949. -
    9950. }
    9951. -
    9952. if (isset($attrs['name'])) {
    9953. -
    9954. $this->currentOperation = $attrs['name'];
    9955. -
    9956. $this->debug("current binding operation: $this->currentOperation");
    9957. -
    9958. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
    9959. -
    9960. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
    9961. -
    9962. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
    9963. -
    9964. }
    9965. -
    9966. break;
    9967. -
    9968. case 'input':
    9969. -
    9970. $this->opStatus = 'input';
    9971. -
    9972. break;
    9973. -
    9974. case 'output':
    9975. -
    9976. $this->opStatus = 'output';
    9977. -
    9978. break;
    9979. -
    9980. case 'body':
    9981. -
    9982. if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
    9983. -
    9984. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
    9985. -
    9986. } else {
    9987. -
    9988. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
    9989. -
    9990. }
    9991. -
    9992. break;
    9993. -
    9994. }
    9995. -
    9996. break;
    9997. -
    9998. case 'service':
    9999. -
    10000. switch ($name) {
    10001. -
    10002. case 'port':
    10003. -
    10004. $this->currentPort = $attrs['name'];
    10005. -
    10006. $this->debug('current port: ' . $this->currentPort);
    10007. -
    10008. $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
    10009. -
    10010. -
    10011. break;
    10012. -
    10013. case 'address':
    10014. -
    10015. $this->ports[$this->currentPort]['location'] = $attrs['location'];
    10016. -
    10017. $this->ports[$this->currentPort]['bindingType'] = $namespace;
    10018. -
    10019. $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
    10020. -
    10021. $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
    10022. -
    10023. break;
    10024. -
    10025. }
    10026. -
    10027. break;
    10028. -
    10029. }
    10030. -
    10031. // set status
    10032. -
    10033. switch ($name) {
    10034. -
    10035. case 'import':
    10036. -
    10037. if (isset($attrs['location'])) {
    10038. -
    10039. $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
    10040. -
    10041. $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
    10042. -
    10043. } else {
    10044. -
    10045. $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
    10046. -
    10047. if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
    10048. -
    10049. $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
    10050. -
    10051. }
    10052. -
    10053. $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
    10054. -
    10055. }
    10056. -
    10057. break;
    10058. -
    10059. //wait for schema
    10060. -
    10061. //case 'types':
    10062. -
    10063. // $this->status = 'schema';
    10064. -
    10065. // break;
    10066. -
    10067. case 'message':
    10068. -
    10069. $this->status = 'message';
    10070. -
    10071. $this->messages[$attrs['name']] = array();
    10072. -
    10073. $this->currentMessage = $attrs['name'];
    10074. -
    10075. break;
    10076. -
    10077. case 'portType':
    10078. -
    10079. $this->status = 'portType';
    10080. -
    10081. $this->portTypes[$attrs['name']] = array();
    10082. -
    10083. $this->currentPortType = $attrs['name'];
    10084. -
    10085. break;
    10086. -
    10087. case "binding":
    10088. -
    10089. if (isset($attrs['name'])) {
    10090. -
    10091. // get binding name
    10092. -
    10093. if (strpos($attrs['name'], ':')) {
    10094. -
    10095. $this->currentBinding = $this->getLocalPart($attrs['name']);
    10096. -
    10097. } else {
    10098. -
    10099. $this->currentBinding = $attrs['name'];
    10100. -
    10101. }
    10102. -
    10103. $this->status = 'binding';
    10104. -
    10105. $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
    10106. -
    10107. $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
    10108. -
    10109. }
    10110. -
    10111. break;
    10112. -
    10113. case 'service':
    10114. -
    10115. $this->serviceName = $attrs['name'];
    10116. -
    10117. $this->status = 'service';
    10118. -
    10119. $this->debug('current service: ' . $this->serviceName);
    10120. -
    10121. break;
    10122. -
    10123. case 'definitions':
    10124. -
    10125. foreach ($attrs as $name => $value) {
    10126. -
    10127. $this->wsdl_info[$name] = $value;
    10128. -
    10129. }
    10130. -
    10131. break;
    10132. -
    10133. }
    10134. -
    10135. }
    10136. -
    10137. }
    10138. -
    10139.  
    10140. -
    10141. /**
    10142. -
    10143. * end-element handler
    10144. -
    10145. *
    10146. -
    10147. * @param string $parser XML parser object
    10148. -
    10149. * @param string $name element name
    10150. -
    10151. * @access private
    10152. -
    10153. */
    10154. -
    10155. function end_element($parser, $name){
    10156. -
    10157. // unset schema status
    10158. -
    10159. if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
    10160. -
    10161. $this->status = "";
    10162. -
    10163. $this->appendDebug($this->currentSchema->getDebug());
    10164. -
    10165. $this->currentSchema->clearDebug();
    10166. -
    10167. $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
    10168. -
    10169. $this->debug('Parsing WSDL schema done');
    10170. -
    10171. }
    10172. -
    10173. if ($this->status == 'schema') {
    10174. -
    10175. $this->currentSchema->schemaEndElement($parser, $name);
    10176. -
    10177. } else {
    10178. -
    10179. // bring depth down a notch
    10180. -
    10181. $this->depth--;
    10182. -
    10183. }
    10184. -
    10185. // end documentation
    10186. -
    10187. if ($this->documentation) {
    10188. -
    10189. //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
    10190. -
    10191. //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
    10192. -
    10193. $this->documentation = false;
    10194. -
    10195. }
    10196. -
    10197. }
    10198. -
    10199.  
    10200. -
    10201. /**
    10202. -
    10203. * element content handler
    10204. -
    10205. *
    10206. -
    10207. * @param string $parser XML parser object
    10208. -
    10209. * @param string $data element content
    10210. -
    10211. * @access private
    10212. -
    10213. */
    10214. -
    10215. function character_data($parser, $data)
    10216. -
    10217. {
    10218. -
    10219. $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
    10220. -
    10221. if (isset($this->message[$pos]['cdata'])) {
    10222. -
    10223. $this->message[$pos]['cdata'] .= $data;
    10224. -
    10225. }
    10226. -
    10227. if ($this->documentation) {
    10228. -
    10229. $this->documentation .= $data;
    10230. -
    10231. }
    10232. -
    10233. }
    10234. -
    10235.  
    10236. -
    10237. /**
    10238. -
    10239. * if authenticating, set user credentials here
    10240. -
    10241. *
    10242. -
    10243. * @param string $username
    10244. -
    10245. * @param string $password
    10246. -
    10247. * @param string $authtype (basic|digest|certificate|ntlm)
    10248. -
    10249. * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
    10250. -
    10251. * @access public
    10252. -
    10253. */
    10254. -
    10255. function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
    10256. -
    10257. $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
    10258. -
    10259. $this->appendDebug($this->varDump($certRequest));
    10260. -
    10261. $this->username = $username;
    10262. -
    10263. $this->password = $password;
    10264. -
    10265. $this->authtype = $authtype;
    10266. -
    10267. $this->certRequest = $certRequest;
    10268. -
    10269. }
    10270. -
    10271. -
    10272. function getBindingData($binding)
    10273. -
    10274. {
    10275. -
    10276. if (is_array($this->bindings[$binding])) {
    10277. -
    10278. return $this->bindings[$binding];
    10279. -
    10280. }
    10281. -
    10282. }
    10283. -
    10284. -
    10285. /**
    10286. -
    10287. * returns an assoc array of operation names => operation data
    10288. -
    10289. *
    10290. -
    10291. * @param string $portName WSDL port name
    10292. -
    10293. * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
    10294. -
    10295. * @return array
    10296. -
    10297. * @access public
    10298. -
    10299. */
    10300. -
    10301. function getOperations($portName = '', $bindingType = 'soap') {
    10302. -
    10303. $ops = array();
    10304. -
    10305. if ($bindingType == 'soap') {
    10306. -
    10307. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
    10308. -
    10309. } elseif ($bindingType == 'soap12') {
    10310. -
    10311. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
    10312. -
    10313. } else {
    10314. -
    10315. $this->debug("getOperations bindingType $bindingType may not be supported");
    10316. -
    10317. }
    10318. -
    10319. $this->debug("getOperations for port '$portName' bindingType $bindingType");
    10320. -
    10321. // loop thru ports
    10322. -
    10323. foreach($this->ports as $port => $portData) {
    10324. -
    10325. $this->debug("getOperations checking port $port bindingType " . $portData['bindingType']);
    10326. -
    10327. if ($portName == '' || $port == $portName) {
    10328. -
    10329. // binding type of port matches parameter
    10330. -
    10331. if ($portData['bindingType'] == $bindingType) {
    10332. -
    10333. $this->debug("getOperations found port $port bindingType $bindingType");
    10334. -
    10335. //$this->debug("port data: " . $this->varDump($portData));
    10336. -
    10337. //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
    10338. -
    10339. // merge bindings
    10340. -
    10341. if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
    10342. -
    10343. $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
    10344. -
    10345. }
    10346. -
    10347. }
    10348. -
    10349. }
    10350. -
    10351. }
    10352. -
    10353. if (count($ops) == 0) {
    10354. -
    10355. $this->debug("getOperations found no operations for port '$portName' bindingType $bindingType");
    10356. -
    10357. }
    10358. -
    10359. return $ops;
    10360. -
    10361. }
    10362. -
    10363. -
    10364. /**
    10365. -
    10366. * returns an associative array of data necessary for calling an operation
    10367. -
    10368. *
    10369. -
    10370. * @param string $operation name of operation
    10371. -
    10372. * @param string $bindingType type of binding eg: soap, soap12
    10373. -
    10374. * @return array
    10375. -
    10376. * @access public
    10377. -
    10378. */
    10379. -
    10380. function getOperationData($operation, $bindingType = 'soap')
    10381. -
    10382. {
    10383. -
    10384. if ($bindingType == 'soap') {
    10385. -
    10386. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
    10387. -
    10388. } elseif ($bindingType == 'soap12') {
    10389. -
    10390. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
    10391. -
    10392. }
    10393. -
    10394. // loop thru ports
    10395. -
    10396. foreach($this->ports as $port => $portData) {
    10397. -
    10398. // binding type of port matches parameter
    10399. -
    10400. if ($portData['bindingType'] == $bindingType) {
    10401. -
    10402. // get binding
    10403. -
    10404. //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
    10405. -
    10406. foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
    10407. -
    10408. // note that we could/should also check the namespace here
    10409. -
    10410. if ($operation == $bOperation) {
    10411. -
    10412. $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
    10413. -
    10414. return $opData;
    10415. -
    10416. }
    10417. -
    10418. }
    10419. -
    10420. }
    10421. -
    10422. }
    10423. -
    10424. }
    10425. -
    10426. -
    10427. /**
    10428. -
    10429. * returns an associative array of data necessary for calling an operation
    10430. -
    10431. *
    10432. -
    10433. * @param string $soapAction soapAction for operation
    10434. -
    10435. * @param string $bindingType type of binding eg: soap, soap12
    10436. -
    10437. * @return array
    10438. -
    10439. * @access public
    10440. -
    10441. */
    10442. -
    10443. function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
    10444. -
    10445. if ($bindingType == 'soap') {
    10446. -
    10447. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
    10448. -
    10449. } elseif ($bindingType == 'soap12') {
    10450. -
    10451. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
    10452. -
    10453. }
    10454. -
    10455. // loop thru ports
    10456. -
    10457. foreach($this->ports as $port => $portData) {
    10458. -
    10459. // binding type of port matches parameter
    10460. -
    10461. if ($portData['bindingType'] == $bindingType) {
    10462. -
    10463. // loop through operations for the binding
    10464. -
    10465. foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
    10466. -
    10467. if ($opData['soapAction'] == $soapAction) {
    10468. -
    10469. return $opData;
    10470. -
    10471. }
    10472. -
    10473. }
    10474. -
    10475. }
    10476. -
    10477. }
    10478. -
    10479. }
    10480. -
    10481. -
    10482. /**
    10483. -
    10484. * returns an array of information about a given type
    10485. -
    10486. * returns false if no type exists by the given name
    10487. -
    10488. *
    10489. -
    10490. * typeDef = array(
    10491. -
    10492. * 'elements' => array(), // refs to elements array
    10493. -
    10494. * 'restrictionBase' => '',
    10495. -
    10496. * 'phpType' => '',
    10497. -
    10498. * 'order' => '(sequence|all)',
    10499. -
    10500. * 'attrs' => array() // refs to attributes array
    10501. -
    10502. * )
    10503. -
    10504. *
    10505. -
    10506. * @param string $type the type
    10507. -
    10508. * @param string $ns namespace (not prefix) of the type
    10509. -
    10510. * @return mixed
    10511. -
    10512. * @access public
    10513. -
    10514. * @see nusoap_xmlschema
    10515. -
    10516. */
    10517. -
    10518. function getTypeDef($type, $ns) {
    10519. -
    10520. $this->debug("in getTypeDef: type=$type, ns=$ns");
    10521. -
    10522. if ((! $ns) && isset($this->namespaces['tns'])) {
    10523. -
    10524. $ns = $this->namespaces['tns'];
    10525. -
    10526. $this->debug("in getTypeDef: type namespace forced to $ns");
    10527. -
    10528. }
    10529. -
    10530. if (!isset($this->schemas[$ns])) {
    10531. -
    10532. foreach ($this->schemas as $ns0 => $schema0) {
    10533. -
    10534. if (strcasecmp($ns, $ns0) == 0) {
    10535. -
    10536. $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
    10537. -
    10538. $ns = $ns0;
    10539. -
    10540. break;
    10541. -
    10542. }
    10543. -
    10544. }
    10545. -
    10546. }
    10547. -
    10548. if (isset($this->schemas[$ns])) {
    10549. -
    10550. $this->debug("in getTypeDef: have schema for namespace $ns");
    10551. -
    10552. for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
    10553. -
    10554. $xs = &$this->schemas[$ns][$i];
    10555. -
    10556. $t = $xs->getTypeDef($type);
    10557. -
    10558. $this->appendDebug($xs->getDebug());
    10559. -
    10560. $xs->clearDebug();
    10561. -
    10562. if ($t) {
    10563. -
    10564. $this->debug("in getTypeDef: found type $type");
    10565. -
    10566. if (!isset($t['phpType'])) {
    10567. -
    10568. // get info for type to tack onto the element
    10569. -
    10570. $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
    10571. -
    10572. $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
    10573. -
    10574. $etype = $this->getTypeDef($uqType, $ns);
    10575. -
    10576. if ($etype) {
    10577. -
    10578. $this->debug("found type for [element] $type:");
    10579. -
    10580. $this->debug($this->varDump($etype));
    10581. -
    10582. if (isset($etype['phpType'])) {
    10583. -
    10584. $t['phpType'] = $etype['phpType'];
    10585. -
    10586. }
    10587. -
    10588. if (isset($etype['elements'])) {
    10589. -
    10590. $t['elements'] = $etype['elements'];
    10591. -
    10592. }
    10593. -
    10594. if (isset($etype['attrs'])) {
    10595. -
    10596. $t['attrs'] = $etype['attrs'];
    10597. -
    10598. }
    10599. -
    10600. } else {
    10601. -
    10602. $this->debug("did not find type for [element] $type");
    10603. -
    10604. }
    10605. -
    10606. }
    10607. -
    10608. return $t;
    10609. -
    10610. }
    10611. -
    10612. }
    10613. -
    10614. $this->debug("in getTypeDef: did not find type $type");
    10615. -
    10616. } else {
    10617. -
    10618. $this->debug("in getTypeDef: do not have schema for namespace $ns");
    10619. -
    10620. }
    10621. -
    10622. return false;
    10623. -
    10624. }
    10625. -
    10626.  
    10627. -
    10628. /**
    10629. -
    10630. * prints html description of services
    10631. -
    10632. *
    10633. -
    10634. * @access private
    10635. -
    10636. */
    10637. -
    10638. function webDescription(){
    10639. -
    10640. global $HTTP_SERVER_VARS;
    10641. -
    10642.  
    10643. -
    10644. if (isset($_SERVER)) {
    10645. -
    10646. $PHP_SELF = $_SERVER['PHP_SELF'];
    10647. -
    10648. } elseif (isset($HTTP_SERVER_VARS)) {
    10649. -
    10650. $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
    10651. -
    10652. } else {
    10653. -
    10654. $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
    10655. -
    10656. }
    10657. -
    10658.  
    10659. -
    10660. $b = '
    10661. -
    10662. <html><head><title>NuSOAP: '.$this->serviceName.'</title>
    10663. -
    10664. <style type="text/css">
    10665. -
    10666. body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
    10667. -
    10668. p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
    10669. -
    10670. pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
    10671. -
    10672. ul { margin-top: 10px; margin-left: 20px; }
    10673. -
    10674. li { list-style-type: none; margin-top: 10px; color: #000000; }
    10675. -
    10676. .content{
    10677. -
    10678. margin-left: 0px; padding-bottom: 2em; }
    10679. -
    10680. .nav {
    10681. -
    10682. padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
    10683. -
    10684. margin-top: 10px; margin-left: 0px; color: #000000;
    10685. -
    10686. background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
    10687. -
    10688. .title {
    10689. -
    10690. font-family: arial; font-size: 26px; color: #ffffff;
    10691. -
    10692. background-color: #999999; width: 100%;
    10693. -
    10694. margin-left: 0px; margin-right: 0px;
    10695. -
    10696. padding-top: 10px; padding-bottom: 10px;}
    10697. -
    10698. .hidden {
    10699. -
    10700. position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
    10701. -
    10702. font-family: arial; overflow: hidden; width: 600;
    10703. -
    10704. padding: 20px; font-size: 10px; background-color: #999999;
    10705. -
    10706. layer-background-color:#FFFFFF; }
    10707. -
    10708. a,a:active { color: charcoal; font-weight: bold; }
    10709. -
    10710. a:visited { color: #666666; font-weight: bold; }
    10711. -
    10712. a:hover { color: cc3300; font-weight: bold; }
    10713. -
    10714. </style>
    10715. -
    10716. <script language="JavaScript" type="text/javascript">
    10717. -
    10718. <!--
    10719. -
    10720. // POP-UP CAPTIONS...
    10721. -
    10722. function lib_bwcheck(){ //Browsercheck (needed)
    10723. -
    10724. this.ver=navigator.appVersion
    10725. -
    10726. this.agent=navigator.userAgent
    10727. -
    10728. this.dom=document.getElementById?1:0
    10729. -
    10730. this.opera5=this.agent.indexOf("Opera 5")>-1
    10731. -
    10732. this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
    10733. -
    10734. this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
    10735. -
    10736. this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
    10737. -
    10738. this.ie=this.ie4||this.ie5||this.ie6
    10739. -
    10740. this.mac=this.agent.indexOf("Mac")>-1
    10741. -
    10742. this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
    10743. -
    10744. this.ns4=(document.layers && !this.dom)?1:0;
    10745. -
    10746. this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
    10747. -
    10748. return this
    10749. -
    10750. }
    10751. -
    10752. var bw = new lib_bwcheck()
    10753. -
    10754. //Makes crossbrowser object.
    10755. -
    10756. function makeObj(obj){
    10757. -
    10758. this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
    10759. -
    10760. if(!this.evnt) return false
    10761. -
    10762. this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
    10763. -
    10764. this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
    10765. -
    10766. this.writeIt=b_writeIt;
    10767. -
    10768. return this
    10769. -
    10770. }
    10771. -
    10772. // A unit of measure that will be added when setting the position of a layer.
    10773. -
    10774. //var px = bw.ns4||window.opera?"":"px";
    10775. -
    10776. function b_writeIt(text){
    10777. -
    10778. if (bw.ns4){this.wref.write(text);this.wref.close()}
    10779. -
    10780. else this.wref.innerHTML = text
    10781. -
    10782. }
    10783. -
    10784. //Shows the messages
    10785. -
    10786. var oDesc;
    10787. -
    10788. function popup(divid){
    10789. -
    10790. if(oDesc = new makeObj(divid)){
    10791. -
    10792. oDesc.css.visibility = "visible"
    10793. -
    10794. }
    10795. -
    10796. }
    10797. -
    10798. function popout(){ // Hides message
    10799. -
    10800. if(oDesc) oDesc.css.visibility = "hidden"
    10801. -
    10802. }
    10803. -
    10804. //-->
    10805. -
    10806. </script>
    10807. -
    10808. </head>
    10809. -
    10810. <body>
    10811. -
    10812. <div class=content>
    10813. -
    10814. <br><br>
    10815. -
    10816. <div class=title>'.$this->serviceName.'</div>
    10817. -
    10818. <div class=nav>
    10819. -
    10820. <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
    10821. -
    10822. Click on an operation name to view it&apos;s details.</p>
    10823. -
    10824. <ul>';
    10825. -
    10826. foreach($this->getOperations() as $op => $data){
    10827. -
    10828. $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
    10829. -
    10830. // create hidden div
    10831. -
    10832. $b .= "<div id='$op' class='hidden'>
    10833. -
    10834. <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
    10835. -
    10836. foreach($data as $donnie => $marie){ // loop through opdata
    10837. -
    10838. if($donnie == 'input' || $donnie == 'output'){ // show input/output data
    10839. -
    10840. $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
    10841. -
    10842. foreach($marie as $captain => $tenille){ // loop through data
    10843. -
    10844. if($captain == 'parts'){ // loop thru parts
    10845. -
    10846. $b .= "&nbsp;&nbsp;$captain:<br>";
    10847. -
    10848. //if(is_array($tenille)){
    10849. -
    10850. foreach($tenille as $joanie => $chachi){
    10851. -
    10852. $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
    10853. -
    10854. }
    10855. -
    10856. //}
    10857. -
    10858. } else {
    10859. -
    10860. $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
    10861. -
    10862. }
    10863. -
    10864. }
    10865. -
    10866. } else {
    10867. -
    10868. $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
    10869. -
    10870. }
    10871. -
    10872. }
    10873. -
    10874. $b .= '</div>';
    10875. -
    10876. }
    10877. -
    10878. $b .= '
    10879. -
    10880. <ul>
    10881. -
    10882. </div>
    10883. -
    10884. </div></body></html>';
    10885. -
    10886. return $b;
    10887. -
    10888. }
    10889. -
    10890.  
    10891. -
    10892. /**
    10893. -
    10894. * serialize the parsed wsdl
    10895. -
    10896. *
    10897. -
    10898. * @param mixed $debug whether to put debug=1 in endpoint URL
    10899. -
    10900. * @return string serialization of WSDL
    10901. -
    10902. * @access public
    10903. -
    10904. */
    10905. -
    10906. function serialize($debug = 0)
    10907. -
    10908. {
    10909. -
    10910. $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
    10911. -
    10912. $xml .= "\n<definitions";
    10913. -
    10914. foreach($this->namespaces as $k => $v) {
    10915. -
    10916. $xml .= " xmlns:$k=\"$v\"";
    10917. -
    10918. }
    10919. -
    10920. // 10.9.02 - add poulter fix for wsdl and tns declarations
    10921. -
    10922. if (isset($this->namespaces['wsdl'])) {
    10923. -
    10924. $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
    10925. -
    10926. }
    10927. -
    10928. if (isset($this->namespaces['tns'])) {
    10929. -
    10930. $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
    10931. -
    10932. }
    10933. -
    10934. $xml .= '>';
    10935. -
    10936. // imports
    10937. -
    10938. if (sizeof($this->import) > 0) {
    10939. -
    10940. foreach($this->import as $ns => $list) {
    10941. -
    10942. foreach ($list as $ii) {
    10943. -
    10944. if ($ii['location'] != '') {
    10945. -
    10946. $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
    10947. -
    10948. } else {
    10949. -
    10950. $xml .= '<import namespace="' . $ns . '" />';
    10951. -
    10952. }
    10953. -
    10954. }
    10955. -
    10956. }
    10957. -
    10958. }
    10959. -
    10960. // types
    10961. -
    10962. if (count($this->schemas)>=1) {
    10963. -
    10964. $xml .= "\n<types>\n";
    10965. -
    10966. foreach ($this->schemas as $ns => $list) {
    10967. -
    10968. foreach ($list as $xs) {
    10969. -
    10970. $xml .= $xs->serializeSchema();
    10971. -
    10972. }
    10973. -
    10974. }
    10975. -
    10976. $xml .= '</types>';
    10977. -
    10978. }
    10979. -
    10980. // messages
    10981. -
    10982. if (count($this->messages) >= 1) {
    10983. -
    10984. foreach($this->messages as $msgName => $msgParts) {
    10985. -
    10986. $xml .= "\n<message name=\"" . $msgName . '">';
    10987. -
    10988. if(is_array($msgParts)){
    10989. -
    10990. foreach($msgParts as $partName => $partType) {
    10991. -
    10992. // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
    10993. -
    10994. if (strpos($partType, ':')) {
    10995. -
    10996. $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
    10997. -
    10998. } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
    10999. -
    11000. // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
    11001. -
    11002. $typePrefix = 'xsd';
    11003. -
    11004. } else {
    11005. -
    11006. foreach($this->typemap as $ns => $types) {
    11007. -
    11008. if (isset($types[$partType])) {
    11009. -
    11010. $typePrefix = $this->getPrefixFromNamespace($ns);
    11011. -
    11012. }
    11013. -
    11014. }
    11015. -
    11016. if (!isset($typePrefix)) {
    11017. -
    11018. die("$partType has no namespace!");
    11019. -
    11020. }
    11021. -
    11022. }
    11023. -
    11024. $ns = $this->getNamespaceFromPrefix($typePrefix);
    11025. -
    11026. $localPart = $this->getLocalPart($partType);
    11027. -
    11028. $typeDef = $this->getTypeDef($localPart, $ns);
    11029. -
    11030. if ($typeDef['typeClass'] == 'element') {
    11031. -
    11032. $elementortype = 'element';
    11033. -
    11034. if (substr($localPart, -1) == '^') {
    11035. -
    11036. $localPart = substr($localPart, 0, -1);
    11037. -
    11038. }
    11039. -
    11040. } else {
    11041. -
    11042. $elementortype = 'type';
    11043. -
    11044. }
    11045. -
    11046. $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
    11047. -
    11048. }
    11049. -
    11050. }
    11051. -
    11052. $xml .= '</message>';
    11053. -
    11054. }
    11055. -
    11056. }
    11057. -
    11058. // bindings & porttypes
    11059. -
    11060. if (count($this->bindings) >= 1) {
    11061. -
    11062. $binding_xml = '';
    11063. -
    11064. $portType_xml = '';
    11065. -
    11066. foreach($this->bindings as $bindingName => $attrs) {
    11067. -
    11068. $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
    11069. -
    11070. $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
    11071. -
    11072. $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
    11073. -
    11074. foreach($attrs['operations'] as $opName => $opParts) {
    11075. -
    11076. $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
    11077. -
    11078. $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
    11079. -
    11080. if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
    11081. -
    11082. $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
    11083. -
    11084. } else {
    11085. -
    11086. $enc_style = '';
    11087. -
    11088. }
    11089. -
    11090. $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
    11091. -
    11092. if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
    11093. -
    11094. $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
    11095. -
    11096. } else {
    11097. -
    11098. $enc_style = '';
    11099. -
    11100. }
    11101. -
    11102. $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
    11103. -
    11104. $binding_xml .= "\n" . ' </operation>';
    11105. -
    11106. $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
    11107. -
    11108. if (isset($opParts['parameterOrder'])) {
    11109. -
    11110. $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
    11111. -
    11112. }
    11113. -
    11114. $portType_xml .= '>';
    11115. -
    11116. if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
    11117. -
    11118. $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
    11119. -
    11120. }
    11121. -
    11122. $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
    11123. -
    11124. $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
    11125. -
    11126. $portType_xml .= "\n" . ' </operation>';
    11127. -
    11128. }
    11129. -
    11130. $portType_xml .= "\n" . '</portType>';
    11131. -
    11132. $binding_xml .= "\n" . '</binding>';
    11133. -
    11134. }
    11135. -
    11136. $xml .= $portType_xml . $binding_xml;
    11137. -
    11138. }
    11139. -
    11140. // services
    11141. -
    11142. $xml .= "\n<service name=\"" . $this->serviceName . '">';
    11143. -
    11144. if (count($this->ports) >= 1) {
    11145. -
    11146. foreach($this->ports as $pName => $attrs) {
    11147. -
    11148. $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
    11149. -
    11150. $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
    11151. -
    11152. $xml .= "\n" . ' </port>';
    11153. -
    11154. }
    11155. -
    11156. }
    11157. -
    11158. $xml .= "\n" . '</service>';
    11159. -
    11160. return $xml . "\n</definitions>";
    11161. -
    11162. }
    11163. -
    11164.  
    11165. -
    11166. /**
    11167. -
    11168. * determine whether a set of parameters are unwrapped
    11169. -
    11170. * when they are expect to be wrapped, Microsoft-style.
    11171. -
    11172. *
    11173. -
    11174. * @param string $type the type (element name) of the wrapper
    11175. -
    11176. * @param array $parameters the parameter values for the SOAP call
    11177. -
    11178. * @return boolean whether they parameters are unwrapped (and should be wrapped)
    11179. -
    11180. * @access private
    11181. -
    11182. */
    11183. -
    11184. function parametersMatchWrapped($type, &$parameters) {
    11185. -
    11186. $this->debug("in parametersMatchWrapped type=$type, parameters=");
    11187. -
    11188. $this->appendDebug($this->varDump($parameters));
    11189. -
    11190.  
    11191. -
    11192. // split type into namespace:unqualified-type
    11193. -
    11194. if (strpos($type, ':')) {
    11195. -
    11196. $uqType = substr($type, strrpos($type, ':') + 1);
    11197. -
    11198. $ns = substr($type, 0, strrpos($type, ':'));
    11199. -
    11200. $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
    11201. -
    11202. if ($this->getNamespaceFromPrefix($ns)) {
    11203. -
    11204. $ns = $this->getNamespaceFromPrefix($ns);
    11205. -
    11206. $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
    11207. -
    11208. }
    11209. -
    11210. } else {
    11211. -
    11212. // TODO: should the type be compared to types in XSD, and the namespace
    11213. -
    11214. // set to XSD if the type matches?
    11215. -
    11216. $this->debug("in parametersMatchWrapped: No namespace for type $type");
    11217. -
    11218. $ns = '';
    11219. -
    11220. $uqType = $type;
    11221. -
    11222. }
    11223. -
    11224.  
    11225. -
    11226. // get the type information
    11227. -
    11228. if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
    11229. -
    11230. $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
    11231. -
    11232. return false;
    11233. -
    11234. }
    11235. -
    11236. $this->debug("in parametersMatchWrapped: found typeDef=");
    11237. -
    11238. $this->appendDebug($this->varDump($typeDef));
    11239. -
    11240. if (substr($uqType, -1) == '^') {
    11241. -
    11242. $uqType = substr($uqType, 0, -1);
    11243. -
    11244. }
    11245. -
    11246. $phpType = $typeDef['phpType'];
    11247. -
    11248. $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
    11249. -
    11250. $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
    11251. -
    11252. -
    11253. // we expect a complexType or element of complexType
    11254. -
    11255. if ($phpType != 'struct') {
    11256. -
    11257. $this->debug("in parametersMatchWrapped: not a struct");
    11258. -
    11259. return false;
    11260. -
    11261. }
    11262. -
    11263.  
    11264. -
    11265. // see whether the parameter names match the elements
    11266. -
    11267. if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
    11268. -
    11269. $elements = 0;
    11270. -
    11271. $matches = 0;
    11272. -
    11273. foreach ($typeDef['elements'] as $name => $attrs) {
    11274. -
    11275. if (isset($parameters[$name])) {
    11276. -
    11277. $this->debug("in parametersMatchWrapped: have parameter named $name");
    11278. -
    11279. $matches++;
    11280. -
    11281. } else {
    11282. -
    11283. $this->debug("in parametersMatchWrapped: do not have parameter named $name");
    11284. -
    11285. }
    11286. -
    11287. $elements++;
    11288. -
    11289. }
    11290. -
    11291.  
    11292. -
    11293. $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
    11294. -
    11295. if ($matches == 0) {
    11296. -
    11297. return false;
    11298. -
    11299. }
    11300. -
    11301. return true;
    11302. -
    11303. }
    11304. -
    11305.  
    11306. -
    11307. // since there are no elements for the type, if the user passed no
    11308. -
    11309. // parameters, the parameters match wrapped.
    11310. -
    11311. $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
    11312. -
    11313. return count($parameters) == 0;
    11314. -
    11315. }
    11316. -
    11317.  
    11318. -
    11319. /**
    11320. -
    11321. * serialize PHP values according to a WSDL message definition
    11322. -
    11323. * contrary to the method name, this is not limited to RPC
    11324. -
    11325. *
    11326. -
    11327. * TODO
    11328. -
    11329. * - multi-ref serialization
    11330. -
    11331. * - validate PHP values against type definitions, return errors if invalid
    11332. -
    11333. *
    11334. -
    11335. * @param string $operation operation name
    11336. -
    11337. * @param string $direction (input|output)
    11338. -
    11339. * @param mixed $parameters parameter value(s)
    11340. -
    11341. * @param string $bindingType (soap|soap12)
    11342. -
    11343. * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
    11344. -
    11345. * @access public
    11346. -
    11347. */
    11348. -
    11349. function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
    11350. -
    11351. $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
    11352. -
    11353. $this->appendDebug('parameters=' . $this->varDump($parameters));
    11354. -
    11355. -
    11356. if ($direction != 'input' && $direction != 'output') {
    11357. -
    11358. $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
    11359. -
    11360. $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
    11361. -
    11362. return false;
    11363. -
    11364. }
    11365. -
    11366. if (!$opData = $this->getOperationData($operation, $bindingType)) {
    11367. -
    11368. $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
    11369. -
    11370. $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
    11371. -
    11372. return false;
    11373. -
    11374. }
    11375. -
    11376. $this->debug('in serializeRPCParameters: opData:');
    11377. -
    11378. $this->appendDebug($this->varDump($opData));
    11379. -
    11380.  
    11381. -
    11382. // Get encoding style for output and set to current
    11383. -
    11384. $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
    11385. -
    11386. if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
    11387. -
    11388. $encodingStyle = $opData['output']['encodingStyle'];
    11389. -
    11390. $enc_style = $encodingStyle;
    11391. -
    11392. }
    11393. -
    11394.  
    11395. -
    11396. // set input params
    11397. -
    11398. $xml = '';
    11399. -
    11400. if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
    11401. -
    11402. $parts = &$opData[$direction]['parts'];
    11403. -
    11404. $part_count = sizeof($parts);
    11405. -
    11406. $style = $opData['style'];
    11407. -
    11408. $use = $opData[$direction]['use'];
    11409. -
    11410. $this->debug("have $part_count part(s) to serialize using $style/$use");
    11411. -
    11412. if (is_array($parameters)) {
    11413. -
    11414. $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
    11415. -
    11416. $parameter_count = count($parameters);
    11417. -
    11418. $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
    11419. -
    11420. // check for Microsoft-style wrapped parameters
    11421. -
    11422. if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
    11423. -
    11424. $this->debug('check whether the caller has wrapped the parameters');
    11425. -
    11426. if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) {
    11427. -
    11428. // TODO: consider checking here for double-wrapping, when
    11429. -
    11430. // service function wraps, then NuSOAP wraps again
    11431. -
    11432. $this->debug("change simple array to associative with 'parameters' element");
    11433. -
    11434. $parameters['parameters'] = $parameters[0];
    11435. -
    11436. unset($parameters[0]);
    11437. -
    11438. }
    11439. -
    11440. if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) {
    11441. -
    11442. $this->debug('check whether caller\'s parameters match the wrapped ones');
    11443. -
    11444. if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
    11445. -
    11446. $this->debug('wrap the parameters for the caller');
    11447. -
    11448. $parameters = array('parameters' => $parameters);
    11449. -
    11450. $parameter_count = 1;
    11451. -
    11452. }
    11453. -
    11454. }
    11455. -
    11456. }
    11457. -
    11458. foreach ($parts as $name => $type) {
    11459. -
    11460. $this->debug("serializing part $name of type $type");
    11461. -
    11462. // Track encoding style
    11463. -
    11464. if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
    11465. -
    11466. $encodingStyle = $opData[$direction]['encodingStyle'];
    11467. -
    11468. $enc_style = $encodingStyle;
    11469. -
    11470. } else {
    11471. -
    11472. $enc_style = false;
    11473. -
    11474. }
    11475. -
    11476. // NOTE: add error handling here
    11477. -
    11478. // if serializeType returns false, then catch global error and fault
    11479. -
    11480. if ($parametersArrayType == 'arraySimple') {
    11481. -
    11482. $p = array_shift($parameters);
    11483. -
    11484. $this->debug('calling serializeType w/indexed param');
    11485. -
    11486. $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
    11487. -
    11488. } elseif (isset($parameters[$name])) {
    11489. -
    11490. $this->debug('calling serializeType w/named param');
    11491. -
    11492. $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
    11493. -
    11494. } else {
    11495. -
    11496. // TODO: only send nillable
    11497. -
    11498. $this->debug('calling serializeType w/null param');
    11499. -
    11500. $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
    11501. -
    11502. }
    11503. -
    11504. }
    11505. -
    11506. } else {
    11507. -
    11508. $this->debug('no parameters passed.');
    11509. -
    11510. }
    11511. -
    11512. }
    11513. -
    11514. $this->debug("serializeRPCParameters returning: $xml");
    11515. -
    11516. return $xml;
    11517. -
    11518. }
    11519. -
    11520. -
    11521. /**
    11522. -
    11523. * serialize a PHP value according to a WSDL message definition
    11524. -
    11525. *
    11526. -
    11527. * TODO
    11528. -
    11529. * - multi-ref serialization
    11530. -
    11531. * - validate PHP values against type definitions, return errors if invalid
    11532. -
    11533. *
    11534. -
    11535. * @param string $operation operation name
    11536. -
    11537. * @param string $direction (input|output)
    11538. -
    11539. * @param mixed $parameters parameter value(s)
    11540. -
    11541. * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
    11542. -
    11543. * @access public
    11544. -
    11545. * @deprecated
    11546. -
    11547. */
    11548. -
    11549. function serializeParameters($operation, $direction, $parameters)
    11550. -
    11551. {
    11552. -
    11553. $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
    11554. -
    11555. $this->appendDebug('parameters=' . $this->varDump($parameters));
    11556. -
    11557. -
    11558. if ($direction != 'input' && $direction != 'output') {
    11559. -
    11560. $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
    11561. -
    11562. $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
    11563. -
    11564. return false;
    11565. -
    11566. }
    11567. -
    11568. if (!$opData = $this->getOperationData($operation)) {
    11569. -
    11570. $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
    11571. -
    11572. $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
    11573. -
    11574. return false;
    11575. -
    11576. }
    11577. -
    11578. $this->debug('opData:');
    11579. -
    11580. $this->appendDebug($this->varDump($opData));
    11581. -
    11582. -
    11583. // Get encoding style for output and set to current
    11584. -
    11585. $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
    11586. -
    11587. if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
    11588. -
    11589. $encodingStyle = $opData['output']['encodingStyle'];
    11590. -
    11591. $enc_style = $encodingStyle;
    11592. -
    11593. }
    11594. -
    11595. -
    11596. // set input params
    11597. -
    11598. $xml = '';
    11599. -
    11600. if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
    11601. -
    11602. -
    11603. $use = $opData[$direction]['use'];
    11604. -
    11605. $this->debug("use=$use");
    11606. -
    11607. $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
    11608. -
    11609. if (is_array($parameters)) {
    11610. -
    11611. $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
    11612. -
    11613. $this->debug('have ' . $parametersArrayType . ' parameters');
    11614. -
    11615. foreach($opData[$direction]['parts'] as $name => $type) {
    11616. -
    11617. $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
    11618. -
    11619. // Track encoding style
    11620. -
    11621. if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
    11622. -
    11623. $encodingStyle = $opData[$direction]['encodingStyle'];
    11624. -
    11625. $enc_style = $encodingStyle;
    11626. -
    11627. } else {
    11628. -
    11629. $enc_style = false;
    11630. -
    11631. }
    11632. -
    11633. // NOTE: add error handling here
    11634. -
    11635. // if serializeType returns false, then catch global error and fault
    11636. -
    11637. if ($parametersArrayType == 'arraySimple') {
    11638. -
    11639. $p = array_shift($parameters);
    11640. -
    11641. $this->debug('calling serializeType w/indexed param');
    11642. -
    11643. $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
    11644. -
    11645. } elseif (isset($parameters[$name])) {
    11646. -
    11647. $this->debug('calling serializeType w/named param');
    11648. -
    11649. $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
    11650. -
    11651. } else {
    11652. -
    11653. // TODO: only send nillable
    11654. -
    11655. $this->debug('calling serializeType w/null param');
    11656. -
    11657. $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
    11658. -
    11659. }
    11660. -
    11661. }
    11662. -
    11663. } else {
    11664. -
    11665. $this->debug('no parameters passed.');
    11666. -
    11667. }
    11668. -
    11669. }
    11670. -
    11671. $this->debug("serializeParameters returning: $xml");
    11672. -
    11673. return $xml;
    11674. -
    11675. }
    11676. -
    11677. -
    11678. /**
    11679. -
    11680. * serializes a PHP value according a given type definition
    11681. -
    11682. *
    11683. -
    11684. * @param string $name name of value (part or element)
    11685. -
    11686. * @param string $type XML schema type of value (type or element)
    11687. -
    11688. * @param mixed $value a native PHP value (parameter value)
    11689. -
    11690. * @param string $use use for part (encoded|literal)
    11691. -
    11692. * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
    11693. -
    11694. * @param boolean $unqualified a kludge for what should be XML namespace form handling
    11695. -
    11696. * @return string value serialized as an XML string
    11697. -
    11698. * @access private
    11699. -
    11700. */
    11701. -
    11702. function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
    11703. -
    11704. {
    11705. -
    11706. $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
    11707. -
    11708. $this->appendDebug("value=" . $this->varDump($value));
    11709. -
    11710. if($use == 'encoded' && $encodingStyle) {
    11711. -
    11712. $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
    11713. -
    11714. }
    11715. -
    11716.  
    11717. -
    11718. // if a soapval has been supplied, let its type override the WSDL
    11719. -
    11720. if (is_object($value) && get_class($value) == 'soapval') {
    11721. -
    11722. if ($value->type_ns) {
    11723. -
    11724. $type = $value->type_ns . ':' . $value->type;
    11725. -
    11726. $forceType = true;
    11727. -
    11728. $this->debug("in serializeType: soapval overrides type to $type");
    11729. -
    11730. } elseif ($value->type) {
    11731. -
    11732. $type = $value->type;
    11733. -
    11734. $forceType = true;
    11735. -
    11736. $this->debug("in serializeType: soapval overrides type to $type");
    11737. -
    11738. } else {
    11739. -
    11740. $forceType = false;
    11741. -
    11742. $this->debug("in serializeType: soapval does not override type");
    11743. -
    11744. }
    11745. -
    11746. $attrs = $value->attributes;
    11747. -
    11748. $value = $value->value;
    11749. -
    11750. $this->debug("in serializeType: soapval overrides value to $value");
    11751. -
    11752. if ($attrs) {
    11753. -
    11754. if (!is_array($value)) {
    11755. -
    11756. $value['!'] = $value;
    11757. -
    11758. }
    11759. -
    11760. foreach ($attrs as $n => $v) {
    11761. -
    11762. $value['!' . $n] = $v;
    11763. -
    11764. }
    11765. -
    11766. $this->debug("in serializeType: soapval provides attributes");
    11767. -
    11768. }
    11769. -
    11770. } else {
    11771. -
    11772. $forceType = false;
    11773. -
    11774. }
    11775. -
    11776.  
    11777. -
    11778. $xml = '';
    11779. -
    11780. if (strpos($type, ':')) {
    11781. -
    11782. $uqType = substr($type, strrpos($type, ':') + 1);
    11783. -
    11784. $ns = substr($type, 0, strrpos($type, ':'));
    11785. -
    11786. $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
    11787. -
    11788. if ($this->getNamespaceFromPrefix($ns)) {
    11789. -
    11790. $ns = $this->getNamespaceFromPrefix($ns);
    11791. -
    11792. $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
    11793. -
    11794. }
    11795. -
    11796.  
    11797. -
    11798. if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
    11799. -
    11800. $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
    11801. -
    11802. if ($unqualified && $use == 'literal') {
    11803. -
    11804. $elementNS = " xmlns=\"\"";
    11805. -
    11806. } else {
    11807. -
    11808. $elementNS = '';
    11809. -
    11810. }
    11811. -
    11812. if (is_null($value)) {
    11813. -
    11814. if ($use == 'literal') {
    11815. -
    11816. // TODO: depends on minOccurs
    11817. -
    11818. $xml = "<$name$elementNS/>";
    11819. -
    11820. } else {
    11821. -
    11822. // TODO: depends on nillable, which should be checked before calling this method
    11823. -
    11824. $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
    11825. -
    11826. }
    11827. -
    11828. $this->debug("in serializeType: returning: $xml");
    11829. -
    11830. return $xml;
    11831. -
    11832. }
    11833. -
    11834. if ($uqType == 'Array') {
    11835. -
    11836. // JBoss/Axis does this sometimes
    11837. -
    11838. return $this->serialize_val($value, $name, false, false, false, false, $use);
    11839. -
    11840. }
    11841. -
    11842. if ($uqType == 'boolean') {
    11843. -
    11844. if ((is_string($value) && $value == 'false') || (! $value)) {
    11845. -
    11846. $value = 'false';
    11847. -
    11848. } else {
    11849. -
    11850. $value = 'true';
    11851. -
    11852. }
    11853. -
    11854. }
    11855. -
    11856. if ($uqType == 'string' && gettype($value) == 'string') {
    11857. -
    11858. $value = $this->expandEntities($value);
    11859. -
    11860. }
    11861. -
    11862. if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
    11863. -
    11864. $value = sprintf("%.0lf", $value);
    11865. -
    11866. }
    11867. -
    11868. // it's a scalar
    11869. -
    11870. // TODO: what about null/nil values?
    11871. -
    11872. // check type isn't a custom type extending xmlschema namespace
    11873. -
    11874. if (!$this->getTypeDef($uqType, $ns)) {
    11875. -
    11876. if ($use == 'literal') {
    11877. -
    11878. if ($forceType) {
    11879. -
    11880. $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
    11881. -
    11882. } else {
    11883. -
    11884. $xml = "<$name$elementNS>$value</$name>";
    11885. -
    11886. }
    11887. -
    11888. } else {
    11889. -
    11890. $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
    11891. -
    11892. }
    11893. -
    11894. $this->debug("in serializeType: returning: $xml");
    11895. -
    11896. return $xml;
    11897. -
    11898. }
    11899. -
    11900. $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
    11901. -
    11902. } else if ($ns == 'http://xml.apache.org/xml-soap') {
    11903. -
    11904. $this->debug('in serializeType: appears to be Apache SOAP type');
    11905. -
    11906. if ($uqType == 'Map') {
    11907. -
    11908. $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
    11909. -
    11910. if (! $tt_prefix) {
    11911. -
    11912. $this->debug('in serializeType: Add namespace for Apache SOAP type');
    11913. -
    11914. $tt_prefix = 'ns' . rand(1000, 9999);
    11915. -
    11916. $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
    11917. -
    11918. // force this to be added to usedNamespaces
    11919. -
    11920. $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
    11921. -
    11922. }
    11923. -
    11924. $contents = '';
    11925. -
    11926. foreach($value as $k => $v) {
    11927. -
    11928. $this->debug("serializing map element: key $k, value $v");
    11929. -
    11930. $contents .= '<item>';
    11931. -
    11932. $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
    11933. -
    11934. $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
    11935. -
    11936. $contents .= '</item>';
    11937. -
    11938. }
    11939. -
    11940. if ($use == 'literal') {
    11941. -
    11942. if ($forceType) {
    11943. -
    11944. $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
    11945. -
    11946. } else {
    11947. -
    11948. $xml = "<$name>$contents</$name>";
    11949. -
    11950. }
    11951. -
    11952. } else {
    11953. -
    11954. $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
    11955. -
    11956. }
    11957. -
    11958. $this->debug("in serializeType: returning: $xml");
    11959. -
    11960. return $xml;
    11961. -
    11962. }
    11963. -
    11964. $this->debug('in serializeType: Apache SOAP type, but only support Map');
    11965. -
    11966. }
    11967. -
    11968. } else {
    11969. -
    11970. // TODO: should the type be compared to types in XSD, and the namespace
    11971. -
    11972. // set to XSD if the type matches?
    11973. -
    11974. $this->debug("in serializeType: No namespace for type $type");
    11975. -
    11976. $ns = '';
    11977. -
    11978. $uqType = $type;
    11979. -
    11980. }
    11981. -
    11982. if(!$typeDef = $this->getTypeDef($uqType, $ns)){
    11983. -
    11984. $this->setError("$type ($uqType) is not a supported type.");
    11985. -
    11986. $this->debug("in serializeType: $type ($uqType) is not a supported type.");
    11987. -
    11988. return false;
    11989. -
    11990. } else {
    11991. -
    11992. $this->debug("in serializeType: found typeDef");
    11993. -
    11994. $this->appendDebug('typeDef=' . $this->varDump($typeDef));
    11995. -
    11996. if (substr($uqType, -1) == '^') {
    11997. -
    11998. $uqType = substr($uqType, 0, -1);
    11999. -
    12000. }
    12001. -
    12002. }
    12003. -
    12004. if (!isset($typeDef['phpType'])) {
    12005. -
    12006. $this->setError("$type ($uqType) has no phpType.");
    12007. -
    12008. $this->debug("in serializeType: $type ($uqType) has no phpType.");
    12009. -
    12010. return false;
    12011. -
    12012. }
    12013. -
    12014. $phpType = $typeDef['phpType'];
    12015. -
    12016. $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
    12017. -
    12018. // if php type == struct, map value to the <all> element names
    12019. -
    12020. if ($phpType == 'struct') {
    12021. -
    12022. if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
    12023. -
    12024. $elementName = $uqType;
    12025. -
    12026. if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
    12027. -
    12028. $elementNS = " xmlns=\"$ns\"";
    12029. -
    12030. } else {
    12031. -
    12032. $elementNS = " xmlns=\"\"";
    12033. -
    12034. }
    12035. -
    12036. } else {
    12037. -
    12038. $elementName = $name;
    12039. -
    12040. if ($unqualified) {
    12041. -
    12042. $elementNS = " xmlns=\"\"";
    12043. -
    12044. } else {
    12045. -
    12046. $elementNS = '';
    12047. -
    12048. }
    12049. -
    12050. }
    12051. -
    12052. if (is_null($value)) {
    12053. -
    12054. if ($use == 'literal') {
    12055. -
    12056. // TODO: depends on minOccurs and nillable
    12057. -
    12058. $xml = "<$elementName$elementNS/>";
    12059. -
    12060. } else {
    12061. -
    12062. $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
    12063. -
    12064. }
    12065. -
    12066. $this->debug("in serializeType: returning: $xml");
    12067. -
    12068. return $xml;
    12069. -
    12070. }
    12071. -
    12072. if (is_object($value)) {
    12073. -
    12074. $value = get_object_vars($value);
    12075. -
    12076. }
    12077. -
    12078. if (is_array($value)) {
    12079. -
    12080. $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
    12081. -
    12082. if ($use == 'literal') {
    12083. -
    12084. if ($forceType) {
    12085. -
    12086. $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
    12087. -
    12088. } else {
    12089. -
    12090. $xml = "<$elementName$elementNS$elementAttrs>";
    12091. -
    12092. }
    12093. -
    12094. } else {
    12095. -
    12096. $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
    12097. -
    12098. }
    12099. -
    12100.  
    12101. -
    12102. if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') {
    12103. -
    12104. if (isset($value['!'])) {
    12105. -
    12106. $xml .= $value['!'];
    12107. -
    12108. $this->debug("in serializeType: serialized simpleContent for type $type");
    12109. -
    12110. } else {
    12111. -
    12112. $this->debug("in serializeType: no simpleContent to serialize for type $type");
    12113. -
    12114. }
    12115. -
    12116. } else {
    12117. -
    12118. // complexContent
    12119. -
    12120. $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
    12121. -
    12122. }
    12123. -
    12124. $xml .= "</$elementName>";
    12125. -
    12126. } else {
    12127. -
    12128. $this->debug("in serializeType: phpType is struct, but value is not an array");
    12129. -
    12130. $this->setError("phpType is struct, but value is not an array: see debug output for details");
    12131. -
    12132. $xml = '';
    12133. -
    12134. }
    12135. -
    12136. } elseif ($phpType == 'array') {
    12137. -
    12138. if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
    12139. -
    12140. $elementNS = " xmlns=\"$ns\"";
    12141. -
    12142. } else {
    12143. -
    12144. if ($unqualified) {
    12145. -
    12146. $elementNS = " xmlns=\"\"";
    12147. -
    12148. } else {
    12149. -
    12150. $elementNS = '';
    12151. -
    12152. }
    12153. -
    12154. }
    12155. -
    12156. if (is_null($value)) {
    12157. -
    12158. if ($use == 'literal') {
    12159. -
    12160. // TODO: depends on minOccurs
    12161. -
    12162. $xml = "<$name$elementNS/>";
    12163. -
    12164. } else {
    12165. -
    12166. $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
    12167. -
    12168. $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
    12169. -
    12170. ":Array\" " .
    12171. -
    12172. $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
    12173. -
    12174. ':arrayType="' .
    12175. -
    12176. $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
    12177. -
    12178. ':' .
    12179. -
    12180. $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
    12181. -
    12182. }
    12183. -
    12184. $this->debug("in serializeType: returning: $xml");
    12185. -
    12186. return $xml;
    12187. -
    12188. }
    12189. -
    12190. if (isset($typeDef['multidimensional'])) {
    12191. -
    12192. $nv = array();
    12193. -
    12194. foreach($value as $v) {
    12195. -
    12196. $cols = ',' . sizeof($v);
    12197. -
    12198. $nv = array_merge($nv, $v);
    12199. -
    12200. }
    12201. -
    12202. $value = $nv;
    12203. -
    12204. } else {
    12205. -
    12206. $cols = '';
    12207. -
    12208. }
    12209. -
    12210. if (is_array($value) && sizeof($value) >= 1) {
    12211. -
    12212. $rows = sizeof($value);
    12213. -
    12214. $contents = '';
    12215. -
    12216. foreach($value as $k => $v) {
    12217. -
    12218. $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
    12219. -
    12220. //if (strpos($typeDef['arrayType'], ':') ) {
    12221. -
    12222. if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
    12223. -
    12224. $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
    12225. -
    12226. } else {
    12227. -
    12228. $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
    12229. -
    12230. }
    12231. -
    12232. }
    12233. -
    12234. } else {
    12235. -
    12236. $rows = 0;
    12237. -
    12238. $contents = null;
    12239. -
    12240. }
    12241. -
    12242. // TODO: for now, an empty value will be serialized as a zero element
    12243. -
    12244. // array. Revisit this when coding the handling of null/nil values.
    12245. -
    12246. if ($use == 'literal') {
    12247. -
    12248. $xml = "<$name$elementNS>"
    12249. -
    12250. .$contents
    12251. -
    12252. ."</$name>";
    12253. -
    12254. } else {
    12255. -
    12256. $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
    12257. -
    12258. $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
    12259. -
    12260. .':arrayType="'
    12261. -
    12262. .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
    12263. -
    12264. .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
    12265. -
    12266. .$contents
    12267. -
    12268. ."</$name>";
    12269. -
    12270. }
    12271. -
    12272. } elseif ($phpType == 'scalar') {
    12273. -
    12274. if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
    12275. -
    12276. $elementNS = " xmlns=\"$ns\"";
    12277. -
    12278. } else {
    12279. -
    12280. if ($unqualified) {
    12281. -
    12282. $elementNS = " xmlns=\"\"";
    12283. -
    12284. } else {
    12285. -
    12286. $elementNS = '';
    12287. -
    12288. }
    12289. -
    12290. }
    12291. -
    12292. if ($use == 'literal') {
    12293. -
    12294. if ($forceType) {
    12295. -
    12296. $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
    12297. -
    12298. } else {
    12299. -
    12300. $xml = "<$name$elementNS>$value</$name>";
    12301. -
    12302. }
    12303. -
    12304. } else {
    12305. -
    12306. $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
    12307. -
    12308. }
    12309. -
    12310. }
    12311. -
    12312. $this->debug("in serializeType: returning: $xml");
    12313. -
    12314. return $xml;
    12315. -
    12316. }
    12317. -
    12318. -
    12319. /**
    12320. -
    12321. * serializes the attributes for a complexType
    12322. -
    12323. *
    12324. -
    12325. * @param array $typeDef our internal representation of an XML schema type (or element)
    12326. -
    12327. * @param mixed $value a native PHP value (parameter value)
    12328. -
    12329. * @param string $ns the namespace of the type
    12330. -
    12331. * @param string $uqType the local part of the type
    12332. -
    12333. * @return string value serialized as an XML string
    12334. -
    12335. * @access private
    12336. -
    12337. */
    12338. -
    12339. function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
    12340. -
    12341. $this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType");
    12342. -
    12343. $xml = '';
    12344. -
    12345. if (isset($typeDef['extensionBase'])) {
    12346. -
    12347. $nsx = $this->getPrefix($typeDef['extensionBase']);
    12348. -
    12349. $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
    12350. -
    12351. if ($this->getNamespaceFromPrefix($nsx)) {
    12352. -
    12353. $nsx = $this->getNamespaceFromPrefix($nsx);
    12354. -
    12355. }
    12356. -
    12357. if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
    12358. -
    12359. $this->debug("serialize attributes for extension base $nsx:$uqTypex");
    12360. -
    12361. $xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex);
    12362. -
    12363. } else {
    12364. -
    12365. $this->debug("extension base $nsx:$uqTypex is not a supported type");
    12366. -
    12367. }
    12368. -
    12369. }
    12370. -
    12371. if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
    12372. -
    12373. $this->debug("serialize attributes for XML Schema type $ns:$uqType");
    12374. -
    12375. if (is_array($value)) {
    12376. -
    12377. $xvalue = $value;
    12378. -
    12379. } elseif (is_object($value)) {
    12380. -
    12381. $xvalue = get_object_vars($value);
    12382. -
    12383. } else {
    12384. -
    12385. $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
    12386. -
    12387. $xvalue = array();
    12388. -
    12389. }
    12390. -
    12391. foreach ($typeDef['attrs'] as $aName => $attrs) {
    12392. -
    12393. if (isset($xvalue['!' . $aName])) {
    12394. -
    12395. $xname = '!' . $aName;
    12396. -
    12397. $this->debug("value provided for attribute $aName with key $xname");
    12398. -
    12399. } elseif (isset($xvalue[$aName])) {
    12400. -
    12401. $xname = $aName;
    12402. -
    12403. $this->debug("value provided for attribute $aName with key $xname");
    12404. -
    12405. } elseif (isset($attrs['default'])) {
    12406. -
    12407. $xname = '!' . $aName;
    12408. -
    12409. $xvalue[$xname] = $attrs['default'];
    12410. -
    12411. $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
    12412. -
    12413. } else {
    12414. -
    12415. $xname = '';
    12416. -
    12417. $this->debug("no value provided for attribute $aName");
    12418. -
    12419. }
    12420. -
    12421. if ($xname) {
    12422. -
    12423. $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
    12424. -
    12425. }
    12426. -
    12427. }
    12428. -
    12429. } else {
    12430. -
    12431. $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
    12432. -
    12433. }
    12434. -
    12435. return $xml;
    12436. -
    12437. }
    12438. -
    12439.  
    12440. -
    12441. /**
    12442. -
    12443. * serializes the elements for a complexType
    12444. -
    12445. *
    12446. -
    12447. * @param array $typeDef our internal representation of an XML schema type (or element)
    12448. -
    12449. * @param mixed $value a native PHP value (parameter value)
    12450. -
    12451. * @param string $ns the namespace of the type
    12452. -
    12453. * @param string $uqType the local part of the type
    12454. -
    12455. * @param string $use use for part (encoded|literal)
    12456. -
    12457. * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
    12458. -
    12459. * @return string value serialized as an XML string
    12460. -
    12461. * @access private
    12462. -
    12463. */
    12464. -
    12465. function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
    12466. -
    12467. $this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType");
    12468. -
    12469. $xml = '';
    12470. -
    12471. if (isset($typeDef['extensionBase'])) {
    12472. -
    12473. $nsx = $this->getPrefix($typeDef['extensionBase']);
    12474. -
    12475. $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
    12476. -
    12477. if ($this->getNamespaceFromPrefix($nsx)) {
    12478. -
    12479. $nsx = $this->getNamespaceFromPrefix($nsx);
    12480. -
    12481. }
    12482. -
    12483. if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
    12484. -
    12485. $this->debug("serialize elements for extension base $nsx:$uqTypex");
    12486. -
    12487. $xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle);
    12488. -
    12489. } else {
    12490. -
    12491. $this->debug("extension base $nsx:$uqTypex is not a supported type");
    12492. -
    12493. }
    12494. -
    12495. }
    12496. -
    12497. if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
    12498. -
    12499. $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
    12500. -
    12501. if (is_array($value)) {
    12502. -
    12503. $xvalue = $value;
    12504. -
    12505. } elseif (is_object($value)) {
    12506. -
    12507. $xvalue = get_object_vars($value);
    12508. -
    12509. } else {
    12510. -
    12511. $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
    12512. -
    12513. $xvalue = array();
    12514. -
    12515. }
    12516. -
    12517. // toggle whether all elements are present - ideally should validate against schema
    12518. -
    12519. if (count($typeDef['elements']) != count($xvalue)){
    12520. -
    12521. $optionals = true;
    12522. -
    12523. }
    12524. -
    12525. foreach ($typeDef['elements'] as $eName => $attrs) {
    12526. -
    12527. if (!isset($xvalue[$eName])) {
    12528. -
    12529. if (isset($attrs['default'])) {
    12530. -
    12531. $xvalue[$eName] = $attrs['default'];
    12532. -
    12533. $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
    12534. -
    12535. }
    12536. -
    12537. }
    12538. -
    12539. // if user took advantage of a minOccurs=0, then only serialize named parameters
    12540. -
    12541. if (isset($optionals)
    12542. -
    12543. && (!isset($xvalue[$eName]))
    12544. -
    12545. && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
    12546. -
    12547. ){
    12548. -
    12549. if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
    12550. -
    12551. $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
    12552. -
    12553. }
    12554. -
    12555. // do nothing
    12556. -
    12557. $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
    12558. -
    12559. } else {
    12560. -
    12561. // get value
    12562. -
    12563. if (isset($xvalue[$eName])) {
    12564. -
    12565. $v = $xvalue[$eName];
    12566. -
    12567. } else {
    12568. -
    12569. $v = null;
    12570. -
    12571. }
    12572. -
    12573. if (isset($attrs['form'])) {
    12574. -
    12575. $unqualified = ($attrs['form'] == 'unqualified');
    12576. -
    12577. } else {
    12578. -
    12579. $unqualified = false;
    12580. -
    12581. }
    12582. -
    12583. if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
    12584. -
    12585. $vv = $v;
    12586. -
    12587. foreach ($vv as $k => $v) {
    12588. -
    12589. if (isset($attrs['type']) || isset($attrs['ref'])) {
    12590. -
    12591. // serialize schema-defined type
    12592. -
    12593. $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
    12594. -
    12595. } else {
    12596. -
    12597. // serialize generic type (can this ever really happen?)
    12598. -
    12599. $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
    12600. -
    12601. $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
    12602. -
    12603. }
    12604. -
    12605. }
    12606. -
    12607. } else {
    12608. -
    12609. if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') {
    12610. -
    12611. // do nothing
    12612. -
    12613. } elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') {
    12614. -
    12615. // TODO: serialize a nil correctly, but for now serialize schema-defined type
    12616. -
    12617. $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
    12618. -
    12619. } elseif (isset($attrs['type']) || isset($attrs['ref'])) {
    12620. -
    12621. // serialize schema-defined type
    12622. -
    12623. $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
    12624. -
    12625. } else {
    12626. -
    12627. // serialize generic type (can this ever really happen?)
    12628. -
    12629. $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
    12630. -
    12631. $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
    12632. -
    12633. }
    12634. -
    12635. }
    12636. -
    12637. }
    12638. -
    12639. }
    12640. -
    12641. } else {
    12642. -
    12643. $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
    12644. -
    12645. }
    12646. -
    12647. return $xml;
    12648. -
    12649. }
    12650. -
    12651.  
    12652. -
    12653. /**
    12654. -
    12655. * adds an XML Schema complex type to the WSDL types
    12656. -
    12657. *
    12658. -
    12659. * @param string $name
    12660. -
    12661. * @param string $typeClass (complexType|simpleType|attribute)
    12662. -
    12663. * @param string $phpType currently supported are array and struct (php assoc array)
    12664. -
    12665. * @param string $compositor (all|sequence|choice)
    12666. -
    12667. * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
    12668. -
    12669. * @param array $elements e.g. array ( name => array(name=>'',type=>'') )
    12670. -
    12671. * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
    12672. -
    12673. * @param string $arrayType as namespace:name (xsd:string)
    12674. -
    12675. * @see nusoap_xmlschema
    12676. -
    12677. * @access public
    12678. -
    12679. */
    12680. -
    12681. function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
    12682. -
    12683. if (count($elements) > 0) {
    12684. -
    12685. $eElements = array();
    12686. -
    12687. foreach($elements as $n => $e){
    12688. -
    12689. // expand each element
    12690. -
    12691. $ee = array();
    12692. -
    12693. foreach ($e as $k => $v) {
    12694. -
    12695. $k = strpos($k,':') ? $this->expandQname($k) : $k;
    12696. -
    12697. $v = strpos($v,':') ? $this->expandQname($v) : $v;
    12698. -
    12699. $ee[$k] = $v;
    12700. -
    12701. }
    12702. -
    12703. $eElements[$n] = $ee;
    12704. -
    12705. }
    12706. -
    12707. $elements = $eElements;
    12708. -
    12709. }
    12710. -
    12711. -
    12712. if (count($attrs) > 0) {
    12713. -
    12714. foreach($attrs as $n => $a){
    12715. -
    12716. // expand each attribute
    12717. -
    12718. foreach ($a as $k => $v) {
    12719. -
    12720. $k = strpos($k,':') ? $this->expandQname($k) : $k;
    12721. -
    12722. $v = strpos($v,':') ? $this->expandQname($v) : $v;
    12723. -
    12724. $aa[$k] = $v;
    12725. -
    12726. }
    12727. -
    12728. $eAttrs[$n] = $aa;
    12729. -
    12730. }
    12731. -
    12732. $attrs = $eAttrs;
    12733. -
    12734. }
    12735. -
    12736.  
    12737. -
    12738. $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
    12739. -
    12740. $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
    12741. -
    12742.  
    12743. -
    12744. $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
    12745. -
    12746. $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
    12747. -
    12748. }
    12749. -
    12750.  
    12751. -
    12752. /**
    12753. -
    12754. * adds an XML Schema simple type to the WSDL types
    12755. -
    12756. *
    12757. -
    12758. * @param string $name
    12759. -
    12760. * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
    12761. -
    12762. * @param string $typeClass (should always be simpleType)
    12763. -
    12764. * @param string $phpType (should always be scalar)
    12765. -
    12766. * @param array $enumeration array of values
    12767. -
    12768. * @see nusoap_xmlschema
    12769. -
    12770. * @access public
    12771. -
    12772. */
    12773. -
    12774. function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
    12775. -
    12776. $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
    12777. -
    12778.  
    12779. -
    12780. $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
    12781. -
    12782. $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
    12783. -
    12784. }
    12785. -
    12786.  
    12787. -
    12788. /**
    12789. -
    12790. * adds an element to the WSDL types
    12791. -
    12792. *
    12793. -
    12794. * @param array $attrs attributes that must include name and type
    12795. -
    12796. * @see nusoap_xmlschema
    12797. -
    12798. * @access public
    12799. -
    12800. */
    12801. -
    12802. function addElement($attrs) {
    12803. -
    12804. $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
    12805. -
    12806. $this->schemas[$typens][0]->addElement($attrs);
    12807. -
    12808. }
    12809. -
    12810.  
    12811. -
    12812. /**
    12813. -
    12814. * register an operation with the server
    12815. -
    12816. *
    12817. -
    12818. * @param string $name operation (method) name
    12819. -
    12820. * @param array $in assoc array of input values: key = param name, value = param type
    12821. -
    12822. * @param array $out assoc array of output values: key = param name, value = param type
    12823. -
    12824. * @param string $namespace optional The namespace for the operation
    12825. -
    12826. * @param string $soapaction optional The soapaction for the operation
    12827. -
    12828. * @param string $style (rpc|document) optional The style for the operation Note: when 'document' is specified, parameter and return wrappers are created for you automatically
    12829. -
    12830. * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
    12831. -
    12832. * @param string $documentation optional The description to include in the WSDL
    12833. -
    12834. * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
    12835. -
    12836. * @access public
    12837. -
    12838. */
    12839. -
    12840. function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
    12841. -
    12842. if ($use == 'encoded' && $encodingStyle == '') {
    12843. -
    12844. $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
    12845. -
    12846. }
    12847. -
    12848.  
    12849. -
    12850. if ($style == 'document') {
    12851. -
    12852. $elements = array();
    12853. -
    12854. foreach ($in as $n => $t) {
    12855. -
    12856. $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
    12857. -
    12858. }
    12859. -
    12860. $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
    12861. -
    12862. $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
    12863. -
    12864. $in = array('parameters' => 'tns:' . $name . '^');
    12865. -
    12866.  
    12867. -
    12868. $elements = array();
    12869. -
    12870. foreach ($out as $n => $t) {
    12871. -
    12872. $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
    12873. -
    12874. }
    12875. -
    12876. $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
    12877. -
    12878. $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
    12879. -
    12880. $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
    12881. -
    12882. }
    12883. -
    12884.  
    12885. -
    12886. // get binding
    12887. -
    12888. $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
    12889. -
    12890. array(
    12891. -
    12892. 'name' => $name,
    12893. -
    12894. 'binding' => $this->serviceName . 'Binding',
    12895. -
    12896. 'endpoint' => $this->endpoint,
    12897. -
    12898. 'soapAction' => $soapaction,
    12899. -
    12900. 'style' => $style,
    12901. -
    12902. 'input' => array(
    12903. -
    12904. 'use' => $use,
    12905. -
    12906. 'namespace' => $namespace,
    12907. -
    12908. 'encodingStyle' => $encodingStyle,
    12909. -
    12910. 'message' => $name . 'Request',
    12911. -
    12912. 'parts' => $in),
    12913. -
    12914. 'output' => array(
    12915. -
    12916. 'use' => $use,
    12917. -
    12918. 'namespace' => $namespace,
    12919. -
    12920. 'encodingStyle' => $encodingStyle,
    12921. -
    12922. 'message' => $name . 'Response',
    12923. -
    12924. 'parts' => $out),
    12925. -
    12926. 'namespace' => $namespace,
    12927. -
    12928. 'transport' => 'http://schemas.xmlsoap.org/soap/http',
    12929. -
    12930. 'documentation' => $documentation);
    12931. -
    12932. // add portTypes
    12933. -
    12934. // add messages
    12935. -
    12936. if($in)
    12937. -
    12938. {
    12939. -
    12940. foreach($in as $pName => $pType)
    12941. -
    12942. {
    12943. -
    12944. if(strpos($pType,':')) {
    12945. -
    12946. $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
    12947. -
    12948. }
    12949. -
    12950. $this->messages[$name.'Request'][$pName] = $pType;
    12951. -
    12952. }
    12953. -
    12954. } else {
    12955. -
    12956. $this->messages[$name.'Request']= '0';
    12957. -
    12958. }
    12959. -
    12960. if($out)
    12961. -
    12962. {
    12963. -
    12964. foreach($out as $pName => $pType)
    12965. -
    12966. {
    12967. -
    12968. if(strpos($pType,':')) {
    12969. -
    12970. $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
    12971. -
    12972. }
    12973. -
    12974. $this->messages[$name.'Response'][$pName] = $pType;
    12975. -
    12976. }
    12977. -
    12978. } else {
    12979. -
    12980. $this->messages[$name.'Response']= '0';
    12981. -
    12982. }
    12983. -
    12984. return true;
    12985. -
    12986. }
    12987. -
    12988. }
    12989. -
    12990. ?><?php
    12991. -
    12992.  
    12993. -
    12994.  
    12995. -
    12996.  
    12997. -
    12998. /**
    12999. -
    13000. *
    13001. -
    13002. * nusoap_parser class parses SOAP XML messages into native PHP values
    13003. -
    13004. *
    13005. -
    13006. * @author Dietrich Ayala <dietrich@ganx4.com>
    13007. -
    13008. * @author Scott Nichol <snichol@users.sourceforge.net>
    13009. -
    13010. * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    13011. -
    13012. * @access public
    13013. -
    13014. */
    13015. -
    13016. class nusoap_parser extends nusoap_base {
    13017. -
    13018.  
    13019. -
    13020. var $xml = '';
    13021. -
    13022. var $xml_encoding = '';
    13023. -
    13024. var $method = '';
    13025. -
    13026. var $root_struct = '';
    13027. -
    13028. var $root_struct_name = '';
    13029. -
    13030. var $root_struct_namespace = '';
    13031. -
    13032. var $root_header = '';
    13033. -
    13034. var $document = ''; // incoming SOAP body (text)
    13035. -
    13036. // determines where in the message we are (envelope,header,body,method)
    13037. -
    13038. -
    13039. var $status = '';
    13040. -
    13041. var $position = 0;
    13042. -
    13043. var $depth = 0;
    13044. -
    13045. var $default_namespace = '';
    13046. -
    13047. var $namespaces = array();
    13048. -
    13049. var $message = array();
    13050. -
    13051. var $parent = '';
    13052. -
    13053. var $fault = false;
    13054. -
    13055. var $fault_code = '';
    13056. -
    13057. var $fault_str = '';
    13058. -
    13059. var $fault_detail = '';
    13060. -
    13061. var $depth_array = array();
    13062. -
    13063. var $debug_flag = true;
    13064. -
    13065. var $soapresponse = NULL; // parsed SOAP Body
    13066. -
    13067. -
    13068. var $soapheader = NULL; // parsed SOAP Header
    13069. -
    13070. -
    13071. var $responseHeaders = ''; // incoming SOAP headers (text)
    13072. -
    13073. -
    13074. var $body_position = 0;
    13075. -
    13076. // for multiref parsing:
    13077. -
    13078. // array of id => pos
    13079. -
    13080. -
    13081. var $ids = array();
    13082. -
    13083. // array of id => hrefs => pos
    13084. -
    13085. -
    13086. var $multirefs = array();
    13087. -
    13088. // toggle for auto-decoding element content
    13089. -
    13090. -
    13091. var $decode_utf8 = true;
    13092. -
    13093.  
    13094. -
    13095. /**
    13096. -
    13097. * constructor that actually does the parsing
    13098. -
    13099. *
    13100. -
    13101. * @param string $xml SOAP message
    13102. -
    13103. * @param string $encoding character encoding scheme of message
    13104. -
    13105. * @param string $method method for which XML is parsed (unused?)
    13106. -
    13107. * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
    13108. -
    13109. * @access public
    13110. -
    13111. */
    13112. -
    13113. function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
    13114. -
    13115. parent::nusoap_base();
    13116. -
    13117. $this->xml = $xml;
    13118. -
    13119. $this->xml_encoding = $encoding;
    13120. -
    13121. $this->method = $method;
    13122. -
    13123. $this->decode_utf8 = $decode_utf8;
    13124. -
    13125.  
    13126. -
    13127. // Check whether content has been read.
    13128. -
    13129. if(!empty($xml)){
    13130. -
    13131. // Check XML encoding
    13132. -
    13133. $pos_xml = strpos($xml, '<?xml');
    13134. -
    13135. if ($pos_xml !== FALSE) {
    13136. -
    13137. $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
    13138. -
    13139. if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
    13140. -
    13141. $xml_encoding = $res[1];
    13142. -
    13143. if (strtoupper($xml_encoding) != $encoding) {
    13144. -
    13145. $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
    13146. -
    13147. $this->debug($err);
    13148. -
    13149. if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
    13150. -
    13151. $this->setError($err);
    13152. -
    13153. return;
    13154. -
    13155. }
    13156. -
    13157. // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
    13158. -
    13159. } else {
    13160. -
    13161. $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
    13162. -
    13163. }
    13164. -
    13165. } else {
    13166. -
    13167. $this->debug('No encoding specified in XML declaration');
    13168. -
    13169. }
    13170. -
    13171. } else {
    13172. -
    13173. $this->debug('No XML declaration');
    13174. -
    13175. }
    13176. -
    13177. $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
    13178. -
    13179. // Create an XML parser - why not xml_parser_create_ns?
    13180. -
    13181. $this->parser = xml_parser_create($this->xml_encoding);
    13182. -
    13183. // Set the options for parsing the XML data.
    13184. -
    13185. //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
    13186. -
    13187. xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
    13188. -
    13189. xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
    13190. -
    13191. // Set the object for the parser.
    13192. -
    13193. xml_set_object($this->parser, $this);
    13194. -
    13195. // Set the element handlers for the parser.
    13196. -
    13197. xml_set_element_handler($this->parser, 'start_element','end_element');
    13198. -
    13199. xml_set_character_data_handler($this->parser,'character_data');
    13200. -
    13201.  
    13202. -
    13203. // Parse the XML file.
    13204. -
    13205. if(!xml_parse($this->parser,$xml,true)){
    13206. -
    13207. // Display an error message.
    13208. -
    13209. $err = sprintf('XML error parsing SOAP payload on line %d: %s',
    13210. -
    13211. xml_get_current_line_number($this->parser),
    13212. -
    13213. xml_error_string(xml_get_error_code($this->parser)));
    13214. -
    13215. $this->debug($err);
    13216. -
    13217. $this->debug("XML payload:\n" . $xml);
    13218. -
    13219. $this->setError($err);
    13220. -
    13221. } else {
    13222. -
    13223. $this->debug('in nusoap_parser ctor, message:');
    13224. -
    13225. $this->appendDebug($this->varDump($this->message));
    13226. -
    13227. $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
    13228. -
    13229. // get final value
    13230. -
    13231. $this->soapresponse = $this->message[$this->root_struct]['result'];
    13232. -
    13233. // get header value
    13234. -
    13235. if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
    13236. -
    13237. $this->soapheader = $this->message[$this->root_header]['result'];
    13238. -
    13239. }
    13240. -
    13241. // resolve hrefs/ids
    13242. -
    13243. if(sizeof($this->multirefs) > 0){
    13244. -
    13245. foreach($this->multirefs as $id => $hrefs){
    13246. -
    13247. $this->debug('resolving multirefs for id: '.$id);
    13248. -
    13249. $idVal = $this->buildVal($this->ids[$id]);
    13250. -
    13251. if (is_array($idVal) && isset($idVal['!id'])) {
    13252. -
    13253. unset($idVal['!id']);
    13254. -
    13255. }
    13256. -
    13257. foreach($hrefs as $refPos => $ref){
    13258. -
    13259. $this->debug('resolving href at pos '.$refPos);
    13260. -
    13261. $this->multirefs[$id][$refPos] = $idVal;
    13262. -
    13263. }
    13264. -
    13265. }
    13266. -
    13267. }
    13268. -
    13269. }
    13270. -
    13271. xml_parser_free($this->parser);
    13272. -
    13273. } else {
    13274. -
    13275. $this->debug('xml was empty, didn\'t parse!');
    13276. -
    13277. $this->setError('xml was empty, didn\'t parse!');
    13278. -
    13279. }
    13280. -
    13281. }
    13282. -
    13283.  
    13284. -
    13285. /**
    13286. -
    13287. * start-element handler
    13288. -
    13289. *
    13290. -
    13291. * @param resource $parser XML parser object
    13292. -
    13293. * @param string $name element name
    13294. -
    13295. * @param array $attrs associative array of attributes
    13296. -
    13297. * @access private
    13298. -
    13299. */
    13300. -
    13301. function start_element($parser, $name, $attrs) {
    13302. -
    13303. // position in a total number of elements, starting from 0
    13304. -
    13305. // update class level pos
    13306. -
    13307. $pos = $this->position++;
    13308. -
    13309. // and set mine
    13310. -
    13311. $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
    13312. -
    13313. // depth = how many levels removed from root?
    13314. -
    13315. // set mine as current global depth and increment global depth value
    13316. -
    13317. $this->message[$pos]['depth'] = $this->depth++;
    13318. -
    13319.  
    13320. -
    13321. // else add self as child to whoever the current parent is
    13322. -
    13323. if($pos != 0){
    13324. -
    13325. $this->message[$this->parent]['children'] .= '|'.$pos;
    13326. -
    13327. }
    13328. -
    13329. // set my parent
    13330. -
    13331. $this->message[$pos]['parent'] = $this->parent;
    13332. -
    13333. // set self as current parent
    13334. -
    13335. $this->parent = $pos;
    13336. -
    13337. // set self as current value for this depth
    13338. -
    13339. $this->depth_array[$this->depth] = $pos;
    13340. -
    13341. // get element prefix
    13342. -
    13343. if(strpos($name,':')){
    13344. -
    13345. // get ns prefix
    13346. -
    13347. $prefix = substr($name,0,strpos($name,':'));
    13348. -
    13349. // get unqualified name
    13350. -
    13351. $name = substr(strstr($name,':'),1);
    13352. -
    13353. }
    13354. -
    13355. // set status
    13356. -
    13357. if ($name == 'Envelope' && $this->status == '') {
    13358. -
    13359. $this->status = 'envelope';
    13360. -
    13361. } elseif ($name == 'Header' && $this->status == 'envelope') {
    13362. -
    13363. $this->root_header = $pos;
    13364. -
    13365. $this->status = 'header';
    13366. -
    13367. } elseif ($name == 'Body' && $this->status == 'envelope'){
    13368. -
    13369. $this->status = 'body';
    13370. -
    13371. $this->body_position = $pos;
    13372. -
    13373. // set method
    13374. -
    13375. } elseif($this->status == 'body' && $pos == ($this->body_position+1)) {
    13376. -
    13377. $this->status = 'method';
    13378. -
    13379. $this->root_struct_name = $name;
    13380. -
    13381. $this->root_struct = $pos;
    13382. -
    13383. $this->message[$pos]['type'] = 'struct';
    13384. -
    13385. $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
    13386. -
    13387. }
    13388. -
    13389. // set my status
    13390. -
    13391. $this->message[$pos]['status'] = $this->status;
    13392. -
    13393. // set name
    13394. -
    13395. $this->message[$pos]['name'] = htmlspecialchars($name);
    13396. -
    13397. // set attrs
    13398. -
    13399. $this->message[$pos]['attrs'] = $attrs;
    13400. -
    13401.  
    13402. -
    13403. // loop through atts, logging ns and type declarations
    13404. -
    13405. $attstr = '';
    13406. -
    13407. foreach($attrs as $key => $value){
    13408. -
    13409. $key_prefix = $this->getPrefix($key);
    13410. -
    13411. $key_localpart = $this->getLocalPart($key);
    13412. -
    13413. // if ns declarations, add to class level array of valid namespaces
    13414. -
    13415. if($key_prefix == 'xmlns'){
    13416. -
    13417. if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){
    13418. -
    13419. $this->XMLSchemaVersion = $value;
    13420. -
    13421. $this->namespaces['xsd'] = $this->XMLSchemaVersion;
    13422. -
    13423. $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
    13424. -
    13425. }
    13426. -
    13427. $this->namespaces[$key_localpart] = $value;
    13428. -
    13429. // set method namespace
    13430. -
    13431. if($name == $this->root_struct_name){
    13432. -
    13433. $this->methodNamespace = $value;
    13434. -
    13435. }
    13436. -
    13437. // if it's a type declaration, set type
    13438. -
    13439. } elseif($key_localpart == 'type'){
    13440. -
    13441. if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
    13442. -
    13443. // do nothing: already processed arrayType
    13444. -
    13445. } else {
    13446. -
    13447. $value_prefix = $this->getPrefix($value);
    13448. -
    13449. $value_localpart = $this->getLocalPart($value);
    13450. -
    13451. $this->message[$pos]['type'] = $value_localpart;
    13452. -
    13453. $this->message[$pos]['typePrefix'] = $value_prefix;
    13454. -
    13455. if(isset($this->namespaces[$value_prefix])){
    13456. -
    13457. $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
    13458. -
    13459. } else if(isset($attrs['xmlns:'.$value_prefix])) {
    13460. -
    13461. $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
    13462. -
    13463. }
    13464. -
    13465. // should do something here with the namespace of specified type?
    13466. -
    13467. }
    13468. -
    13469. } elseif($key_localpart == 'arrayType'){
    13470. -
    13471. $this->message[$pos]['type'] = 'array';
    13472. -
    13473. /* do arrayType ereg here
    13474. -
    13475. [1] arrayTypeValue ::= atype asize
    13476. -
    13477. [2] atype ::= QName rank*
    13478. -
    13479. [3] rank ::= '[' (',')* ']'
    13480. -
    13481. [4] asize ::= '[' length~ ']'
    13482. -
    13483. [5] length ::= nextDimension* Digit+
    13484. -
    13485. [6] nextDimension ::= Digit+ ','
    13486. -
    13487. */
    13488. -
    13489. $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
    13490. -
    13491. if(preg_match($expr,$value,$regs)){
    13492. -
    13493. $this->message[$pos]['typePrefix'] = $regs[1];
    13494. -
    13495. $this->message[$pos]['arrayTypePrefix'] = $regs[1];
    13496. -
    13497. if (isset($this->namespaces[$regs[1]])) {
    13498. -
    13499. $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
    13500. -
    13501. } else if (isset($attrs['xmlns:'.$regs[1]])) {
    13502. -
    13503. $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
    13504. -
    13505. }
    13506. -
    13507. $this->message[$pos]['arrayType'] = $regs[2];
    13508. -
    13509. $this->message[$pos]['arraySize'] = $regs[3];
    13510. -
    13511. $this->message[$pos]['arrayCols'] = $regs[4];
    13512. -
    13513. }
    13514. -
    13515. // specifies nil value (or not)
    13516. -
    13517. } elseif ($key_localpart == 'nil'){
    13518. -
    13519. $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
    13520. -
    13521. // some other attribute
    13522. -
    13523. } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
    13524. -
    13525. $this->message[$pos]['xattrs']['!' . $key] = $value;
    13526. -
    13527. }
    13528. -
    13529.  
    13530. -
    13531. if ($key == 'xmlns') {
    13532. -
    13533. $this->default_namespace = $value;
    13534. -
    13535. }
    13536. -
    13537. // log id
    13538. -
    13539. if($key == 'id'){
    13540. -
    13541. $this->ids[$value] = $pos;
    13542. -
    13543. }
    13544. -
    13545. // root
    13546. -
    13547. if($key_localpart == 'root' && $value == 1){
    13548. -
    13549. $this->status = 'method';
    13550. -
    13551. $this->root_struct_name = $name;
    13552. -
    13553. $this->root_struct = $pos;
    13554. -
    13555. $this->debug("found root struct $this->root_struct_name, pos $pos");
    13556. -
    13557. }
    13558. -
    13559. // for doclit
    13560. -
    13561. $attstr .= " $key=\"$value\"";
    13562. -
    13563. }
    13564. -
    13565. // get namespace - must be done after namespace atts are processed
    13566. -
    13567. if(isset($prefix)){
    13568. -
    13569. $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
    13570. -
    13571. $this->default_namespace = $this->namespaces[$prefix];
    13572. -
    13573. } else {
    13574. -
    13575. $this->message[$pos]['namespace'] = $this->default_namespace;
    13576. -
    13577. }
    13578. -
    13579. if($this->status == 'header'){
    13580. -
    13581. if ($this->root_header != $pos) {
    13582. -
    13583. $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
    13584. -
    13585. }
    13586. -
    13587. } elseif($this->root_struct_name != ''){
    13588. -
    13589. $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
    13590. -
    13591. }
    13592. -
    13593. }
    13594. -
    13595.  
    13596. -
    13597. /**
    13598. -
    13599. * end-element handler
    13600. -
    13601. *
    13602. -
    13603. * @param resource $parser XML parser object
    13604. -
    13605. * @param string $name element name
    13606. -
    13607. * @access private
    13608. -
    13609. */
    13610. -
    13611. function end_element($parser, $name) {
    13612. -
    13613. // position of current element is equal to the last value left in depth_array for my depth
    13614. -
    13615. $pos = $this->depth_array[$this->depth--];
    13616. -
    13617.  
    13618. -
    13619. // get element prefix
    13620. -
    13621. if(strpos($name,':')){
    13622. -
    13623. // get ns prefix
    13624. -
    13625. $prefix = substr($name,0,strpos($name,':'));
    13626. -
    13627. // get unqualified name
    13628. -
    13629. $name = substr(strstr($name,':'),1);
    13630. -
    13631. }
    13632. -
    13633. -
    13634. // build to native type
    13635. -
    13636. if(isset($this->body_position) && $pos > $this->body_position){
    13637. -
    13638. // deal w/ multirefs
    13639. -
    13640. if(isset($this->message[$pos]['attrs']['href'])){
    13641. -
    13642. // get id
    13643. -
    13644. $id = substr($this->message[$pos]['attrs']['href'],1);
    13645. -
    13646. // add placeholder to href array
    13647. -
    13648. $this->multirefs[$id][$pos] = 'placeholder';
    13649. -
    13650. // add set a reference to it as the result value
    13651. -
    13652. $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
    13653. -
    13654. // build complexType values
    13655. -
    13656. } elseif($this->message[$pos]['children'] != ''){
    13657. -
    13658. // if result has already been generated (struct/array)
    13659. -
    13660. if(!isset($this->message[$pos]['result'])){
    13661. -
    13662. $this->message[$pos]['result'] = $this->buildVal($pos);
    13663. -
    13664. }
    13665. -
    13666. // build complexType values of attributes and possibly simpleContent
    13667. -
    13668. } elseif (isset($this->message[$pos]['xattrs'])) {
    13669. -
    13670. if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
    13671. -
    13672. $this->message[$pos]['xattrs']['!'] = null;
    13673. -
    13674. } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
    13675. -
    13676. if (isset($this->message[$pos]['type'])) {
    13677. -
    13678. $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
    13679. -
    13680. } else {
    13681. -
    13682. $parent = $this->message[$pos]['parent'];
    13683. -
    13684. if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
    13685. -
    13686. $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
    13687. -
    13688. } else {
    13689. -
    13690. $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
    13691. -
    13692. }
    13693. -
    13694. }
    13695. -
    13696. }
    13697. -
    13698. $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
    13699. -
    13700. // set value of simpleType (or nil complexType)
    13701. -
    13702. } else {
    13703. -
    13704. //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
    13705. -
    13706. if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
    13707. -
    13708. $this->message[$pos]['xattrs']['!'] = null;
    13709. -
    13710. } elseif (isset($this->message[$pos]['type'])) {
    13711. -
    13712. $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
    13713. -
    13714. } else {
    13715. -
    13716. $parent = $this->message[$pos]['parent'];
    13717. -
    13718. if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
    13719. -
    13720. $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
    13721. -
    13722. } else {
    13723. -
    13724. $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
    13725. -
    13726. }
    13727. -
    13728. }
    13729. -
    13730.  
    13731. -
    13732. /* add value to parent's result, if parent is struct/array
    13733. -
    13734. $parent = $this->message[$pos]['parent'];
    13735. -
    13736. if($this->message[$parent]['type'] != 'map'){
    13737. -
    13738. if(strtolower($this->message[$parent]['type']) == 'array'){
    13739. -
    13740. $this->message[$parent]['result'][] = $this->message[$pos]['result'];
    13741. -
    13742. } else {
    13743. -
    13744. $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
    13745. -
    13746. }
    13747. -
    13748. }
    13749. -
    13750. */
    13751. -
    13752. }
    13753. -
    13754. }
    13755. -
    13756. -
    13757. // for doclit
    13758. -
    13759. if($this->status == 'header'){
    13760. -
    13761. if ($this->root_header != $pos) {
    13762. -
    13763. $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
    13764. -
    13765. }
    13766. -
    13767. } elseif($pos >= $this->root_struct){
    13768. -
    13769. $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
    13770. -
    13771. }
    13772. -
    13773. // switch status
    13774. -
    13775. if ($pos == $this->root_struct){
    13776. -
    13777. $this->status = 'body';
    13778. -
    13779. $this->root_struct_namespace = $this->message[$pos]['namespace'];
    13780. -
    13781. } elseif ($pos == $this->root_header) {
    13782. -
    13783. $this->status = 'envelope';
    13784. -
    13785. } elseif ($name == 'Body' && $this->status == 'body') {
    13786. -
    13787. $this->status = 'envelope';
    13788. -
    13789. } elseif ($name == 'Header' && $this->status == 'header') { // will never happen
    13790. -
    13791. $this->status = 'envelope';
    13792. -
    13793. } elseif ($name == 'Envelope' && $this->status == 'envelope') {
    13794. -
    13795. $this->status = '';
    13796. -
    13797. }
    13798. -
    13799. // set parent back to my parent
    13800. -
    13801. $this->parent = $this->message[$pos]['parent'];
    13802. -
    13803. }
    13804. -
    13805.  
    13806. -
    13807. /**
    13808. -
    13809. * element content handler
    13810. -
    13811. *
    13812. -
    13813. * @param resource $parser XML parser object
    13814. -
    13815. * @param string $data element content
    13816. -
    13817. * @access private
    13818. -
    13819. */
    13820. -
    13821. function character_data($parser, $data){
    13822. -
    13823. $pos = $this->depth_array[$this->depth];
    13824. -
    13825. if ($this->xml_encoding=='UTF-8'){
    13826. -
    13827. // TODO: add an option to disable this for folks who want
    13828. -
    13829. // raw UTF-8 that, e.g., might not map to iso-8859-1
    13830. -
    13831. // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
    13832. -
    13833. if($this->decode_utf8){
    13834. -
    13835. $data = utf8_decode($data);
    13836. -
    13837. }
    13838. -
    13839. }
    13840. -
    13841. $this->message[$pos]['cdata'] .= $data;
    13842. -
    13843. // for doclit
    13844. -
    13845. if($this->status == 'header'){
    13846. -
    13847. $this->responseHeaders .= $data;
    13848. -
    13849. } else {
    13850. -
    13851. $this->document .= $data;
    13852. -
    13853. }
    13854. -
    13855. }
    13856. -
    13857.  
    13858. -
    13859. /**
    13860. -
    13861. * get the parsed message (SOAP Body)
    13862. -
    13863. *
    13864. -
    13865. * @return mixed
    13866. -
    13867. * @access public
    13868. -
    13869. * @deprecated use get_soapbody instead
    13870. -
    13871. */
    13872. -
    13873. function get_response(){
    13874. -
    13875. return $this->soapresponse;
    13876. -
    13877. }
    13878. -
    13879.  
    13880. -
    13881. /**
    13882. -
    13883. * get the parsed SOAP Body (NULL if there was none)
    13884. -
    13885. *
    13886. -
    13887. * @return mixed
    13888. -
    13889. * @access public
    13890. -
    13891. */
    13892. -
    13893. function get_soapbody(){
    13894. -
    13895. return $this->soapresponse;
    13896. -
    13897. }
    13898. -
    13899.  
    13900. -
    13901. /**
    13902. -
    13903. * get the parsed SOAP Header (NULL if there was none)
    13904. -
    13905. *
    13906. -
    13907. * @return mixed
    13908. -
    13909. * @access public
    13910. -
    13911. */
    13912. -
    13913. function get_soapheader(){
    13914. -
    13915. return $this->soapheader;
    13916. -
    13917. }
    13918. -
    13919.  
    13920. -
    13921. /**
    13922. -
    13923. * get the unparsed SOAP Header
    13924. -
    13925. *
    13926. -
    13927. * @return string XML or empty if no Header
    13928. -
    13929. * @access public
    13930. -
    13931. */
    13932. -
    13933. function getHeaders(){
    13934. -
    13935. return $this->responseHeaders;
    13936. -
    13937. }
    13938. -
    13939.  
    13940. -
    13941. /**
    13942. -
    13943. * decodes simple types into PHP variables
    13944. -
    13945. *
    13946. -
    13947. * @param string $value value to decode
    13948. -
    13949. * @param string $type XML type to decode
    13950. -
    13951. * @param string $typens XML type namespace to decode
    13952. -
    13953. * @return mixed PHP value
    13954. -
    13955. * @access private
    13956. -
    13957. */
    13958. -
    13959. function decodeSimple($value, $type, $typens) {
    13960. -
    13961. // TODO: use the namespace!
    13962. -
    13963. if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
    13964. -
    13965. return (string) $value;
    13966. -
    13967. }
    13968. -
    13969. if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
    13970. -
    13971. return (int) $value;
    13972. -
    13973. }
    13974. -
    13975. if ($type == 'float' || $type == 'double' || $type == 'decimal') {
    13976. -
    13977. return (double) $value;
    13978. -
    13979. }
    13980. -
    13981. if ($type == 'boolean') {
    13982. -
    13983. if (strtolower($value) == 'false' || strtolower($value) == 'f') {
    13984. -
    13985. return false;
    13986. -
    13987. }
    13988. -
    13989. return (boolean) $value;
    13990. -
    13991. }
    13992. -
    13993. if ($type == 'base64' || $type == 'base64Binary') {
    13994. -
    13995. $this->debug('Decode base64 value');
    13996. -
    13997. return base64_decode($value);
    13998. -
    13999. }
    14000. -
    14001. // obscure numeric types
    14002. -
    14003. if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
    14004. -
    14005. || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
    14006. -
    14007. || $type == 'unsignedInt'
    14008. -
    14009. || $type == 'unsignedShort' || $type == 'unsignedByte') {
    14010. -
    14011. return (int) $value;
    14012. -
    14013. }
    14014. -
    14015. // bogus: parser treats array with no elements as a simple type
    14016. -
    14017. if ($type == 'array') {
    14018. -
    14019. return array();
    14020. -
    14021. }
    14022. -
    14023. // everything else
    14024. -
    14025. return (string) $value;
    14026. -
    14027. }
    14028. -
    14029.  
    14030. -
    14031. /**
    14032. -
    14033. * builds response structures for compound values (arrays/structs)
    14034. -
    14035. * and scalars
    14036. -
    14037. *
    14038. -
    14039. * @param integer $pos position in node tree
    14040. -
    14041. * @return mixed PHP value
    14042. -
    14043. * @access private
    14044. -
    14045. */
    14046. -
    14047. function buildVal($pos){
    14048. -
    14049. if(!isset($this->message[$pos]['type'])){
    14050. -
    14051. $this->message[$pos]['type'] = '';
    14052. -
    14053. }
    14054. -
    14055. $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
    14056. -
    14057. // if there are children...
    14058. -
    14059. if($this->message[$pos]['children'] != ''){
    14060. -
    14061. $this->debug('in buildVal, there are children');
    14062. -
    14063. $children = explode('|',$this->message[$pos]['children']);
    14064. -
    14065. array_shift($children); // knock off empty
    14066. -
    14067. // md array
    14068. -
    14069. if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
    14070. -
    14071. $r=0; // rowcount
    14072. -
    14073. $c=0; // colcount
    14074. -
    14075. foreach($children as $child_pos){
    14076. -
    14077. $this->debug("in buildVal, got an MD array element: $r, $c");
    14078. -
    14079. $params[$r][] = $this->message[$child_pos]['result'];
    14080. -
    14081. $c++;
    14082. -
    14083. if($c == $this->message[$pos]['arrayCols']){
    14084. -
    14085. $c = 0;
    14086. -
    14087. $r++;
    14088. -
    14089. }
    14090. -
    14091. }
    14092. -
    14093. // array
    14094. -
    14095. } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
    14096. -
    14097. $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
    14098. -
    14099. foreach($children as $child_pos){
    14100. -
    14101. $params[] = &$this->message[$child_pos]['result'];
    14102. -
    14103. }
    14104. -
    14105. // apache Map type: java hashtable
    14106. -
    14107. } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
    14108. -
    14109. $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
    14110. -
    14111. foreach($children as $child_pos){
    14112. -
    14113. $kv = explode("|",$this->message[$child_pos]['children']);
    14114. -
    14115. $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
    14116. -
    14117. }
    14118. -
    14119. // generic compound type
    14120. -
    14121. //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
    14122. -
    14123. } else {
    14124. -
    14125. // Apache Vector type: treat as an array
    14126. -
    14127. $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
    14128. -
    14129. if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
    14130. -
    14131. $notstruct = 1;
    14132. -
    14133. } else {
    14134. -
    14135. $notstruct = 0;
    14136. -
    14137. }
    14138. -
    14139. //
    14140. -
    14141. foreach($children as $child_pos){
    14142. -
    14143. if($notstruct){
    14144. -
    14145. $params[] = &$this->message[$child_pos]['result'];
    14146. -
    14147. } else {
    14148. -
    14149. if (isset($params[$this->message[$child_pos]['name']])) {
    14150. -
    14151. // de-serialize repeated element name into an array
    14152. -
    14153. if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
    14154. -
    14155. $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
    14156. -
    14157. }
    14158. -
    14159. $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
    14160. -
    14161. } else {
    14162. -
    14163. $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
    14164. -
    14165. }
    14166. -
    14167. }
    14168. -
    14169. }
    14170. -
    14171. }
    14172. -
    14173. if (isset($this->message[$pos]['xattrs'])) {
    14174. -
    14175. $this->debug('in buildVal, handling attributes');
    14176. -
    14177. foreach ($this->message[$pos]['xattrs'] as $n => $v) {
    14178. -
    14179. $params[$n] = $v;
    14180. -
    14181. }
    14182. -
    14183. }
    14184. -
    14185. // handle simpleContent
    14186. -
    14187. if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
    14188. -
    14189. $this->debug('in buildVal, handling simpleContent');
    14190. -
    14191. if (isset($this->message[$pos]['type'])) {
    14192. -
    14193. $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
    14194. -
    14195. } else {
    14196. -
    14197. $parent = $this->message[$pos]['parent'];
    14198. -
    14199. if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
    14200. -
    14201. $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
    14202. -
    14203. } else {
    14204. -
    14205. $params['!'] = $this->message[$pos]['cdata'];
    14206. -
    14207. }
    14208. -
    14209. }
    14210. -
    14211. }
    14212. -
    14213. $ret = is_array($params) ? $params : array();
    14214. -
    14215. $this->debug('in buildVal, return:');
    14216. -
    14217. $this->appendDebug($this->varDump($ret));
    14218. -
    14219. return $ret;
    14220. -
    14221. } else {
    14222. -
    14223. $this->debug('in buildVal, no children, building scalar');
    14224. -
    14225. $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
    14226. -
    14227. if (isset($this->message[$pos]['type'])) {
    14228. -
    14229. $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
    14230. -
    14231. $this->debug("in buildVal, return: $ret");
    14232. -
    14233. return $ret;
    14234. -
    14235. }
    14236. -
    14237. $parent = $this->message[$pos]['parent'];
    14238. -
    14239. if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
    14240. -
    14241. $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
    14242. -
    14243. $this->debug("in buildVal, return: $ret");
    14244. -
    14245. return $ret;
    14246. -
    14247. }
    14248. -
    14249. $ret = $this->message[$pos]['cdata'];
    14250. -
    14251. $this->debug("in buildVal, return: $ret");
    14252. -
    14253. return $ret;
    14254. -
    14255. }
    14256. -
    14257. }
    14258. -
    14259. }
    14260. -
    14261.  
    14262. -
    14263. /**
    14264. -
    14265. * Backward compatibility
    14266. -
    14267. */
    14268. -
    14269. class soap_parser extends nusoap_parser {
    14270. -
    14271. }
    14272. -
    14273.  
    14274. -
    14275. ?><?php
    14276. -
    14277.  
    14278. -
    14279.  
    14280. -
    14281.  
    14282. -
    14283. /**
    14284. -
    14285. *
    14286. -
    14287. * [nu]soapclient higher level class for easy usage.
    14288. -
    14289. *
    14290. -
    14291. * usage:
    14292. -
    14293. *
    14294. -
    14295. * // instantiate client with server info
    14296. -
    14297. * $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
    14298. -
    14299. *
    14300. -
    14301. * // call method, get results
    14302. -
    14303. * echo $soapclient->call( string methodname [ ,array parameters] );
    14304. -
    14305. *
    14306. -
    14307. * // bye bye client
    14308. -
    14309. * unset($soapclient);
    14310. -
    14311. *
    14312. -
    14313. * @author Dietrich Ayala <dietrich@ganx4.com>
    14314. -
    14315. * @author Scott Nichol <snichol@users.sourceforge.net>
    14316. -
    14317. * @version $Id: fsource_nusoap__nusoap.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    14318. -
    14319. * @access public
    14320. -
    14321. */
    14322. -
    14323. class nusoap_client extends nusoap_base {
    14324. -
    14325.  
    14326. -
    14327. var $username = ''; // Username for HTTP authentication
    14328. -
    14329. -
    14330. var $password = ''; // Password for HTTP authentication
    14331. -
    14332. -
    14333. var $authtype = ''; // Type of HTTP authentication
    14334. -
    14335. -
    14336. var $certRequest = array(); // Certificate for HTTP SSL authentication
    14337. -
    14338. -
    14339. var $requestHeaders = false; // SOAP headers in request (text)
    14340. -
    14341. -
    14342. var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
    14343. -
    14344. -
    14345. var $responseHeader = NULL; // SOAP Header from response (parsed)
    14346. -
    14347. -
    14348. var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
    14349. -
    14350. -
    14351. var $endpoint;
    14352. -
    14353. var $forceEndpoint = ''; // overrides WSDL endpoint
    14354. -
    14355. -
    14356. var $proxyhost = '';
    14357. -
    14358. var $proxyport = '';
    14359. -
    14360. var $proxyusername = '';
    14361. -
    14362. var $proxypassword = '';
    14363. -
    14364. var $portName = ''; // port name to use in WSDL
    14365. -
    14366. -
    14367. var $xml_encoding = ''; // character set encoding of incoming (response) messages
    14368. -
    14369. -
    14370. var $http_encoding = false;
    14371. -
    14372. var $timeout = 0; // HTTP connection timeout
    14373. -
    14374. -
    14375. var $response_timeout = 30; // HTTP response timeout
    14376. -
    14377. -
    14378. var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
    14379. -
    14380. -
    14381. var $persistentConnection = false;
    14382. -
    14383. var $defaultRpcParams = false; // This is no longer used
    14384. -
    14385. -
    14386. var $request = ''; // HTTP request
    14387. -
    14388. -
    14389. var $response = ''; // HTTP response
    14390. -
    14391. -
    14392. var $responseData = ''; // SOAP payload of response
    14393. -
    14394. -
    14395. var $cookies = array(); // Cookies from response or for request
    14396. -
    14397. -
    14398. var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
    14399. -
    14400. -
    14401. var $operations = array(); // WSDL operations, empty for WSDL initialization error
    14402. -
    14403. -
    14404. var $curl_options = array(); // User-specified cURL options
    14405. -
    14406. -
    14407. var $bindingType = ''; // WSDL operation binding type
    14408. -
    14409. -
    14410. var $use_curl = false; // whether to always try to use cURL
    14411. -
    14412.  
    14413. -
    14414. /*
    14415. -
    14416. * fault related variables
    14417. -
    14418. */
    14419. -
    14420. /**
    14421. -
    14422. * @var fault
    14423. -
    14424. * @access public
    14425. -
    14426. */
    14427. -
    14428. var $fault;
    14429. -
    14430. /**
    14431. -
    14432. * @var faultcode
    14433. -
    14434. * @access public
    14435. -
    14436. */
    14437. -
    14438. var $faultcode;
    14439. -
    14440. /**
    14441. -
    14442. * @var faultstring
    14443. -
    14444. * @access public
    14445. -
    14446. */
    14447. -
    14448. var $faultstring;
    14449. -
    14450. /**
    14451. -
    14452. * @var faultdetail
    14453. -
    14454. * @access public
    14455. -
    14456. */
    14457. -
    14458. var $faultdetail;
    14459. -
    14460.  
    14461. -
    14462. /**
    14463. -
    14464. * constructor
    14465. -
    14466. *
    14467. -
    14468. * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
    14469. -
    14470. * @param mixed $wsdl optional, set to 'wsdl' or true if using WSDL
    14471. -
    14472. * @param string $proxyhost optional
    14473. -
    14474. * @param string $proxyport optional
    14475. -
    14476. * @param string $proxyusername optional
    14477. -
    14478. * @param string $proxypassword optional
    14479. -
    14480. * @param integer $timeout set the connection timeout
    14481. -
    14482. * @param integer $response_timeout set the response timeout
    14483. -
    14484. * @param string $portName optional portName in WSDL document
    14485. -
    14486. * @access public
    14487. -
    14488. */
    14489. -
    14490. function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = ''){
    14491. -
    14492. parent::nusoap_base();
    14493. -
    14494. $this->endpoint = $endpoint;
    14495. -
    14496. $this->proxyhost = $proxyhost;
    14497. -
    14498. $this->proxyport = $proxyport;
    14499. -
    14500. $this->proxyusername = $proxyusername;
    14501. -
    14502. $this->proxypassword = $proxypassword;
    14503. -
    14504. $this->timeout = $timeout;
    14505. -
    14506. $this->response_timeout = $response_timeout;
    14507. -
    14508. $this->portName = $portName;
    14509. -
    14510.  
    14511. -
    14512. $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
    14513. -
    14514. $this->appendDebug('endpoint=' . $this->varDump($endpoint));
    14515. -
    14516.  
    14517. -
    14518. // make values
    14519. -
    14520. if($wsdl){
    14521. -
    14522. if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
    14523. -
    14524. $this->wsdl = $endpoint;
    14525. -
    14526. $this->endpoint = $this->wsdl->wsdl;
    14527. -
    14528. $this->wsdlFile = $this->endpoint;
    14529. -
    14530. $this->debug('existing wsdl instance created from ' . $this->endpoint);
    14531. -
    14532. $this->checkWSDL();
    14533. -
    14534. } else {
    14535. -
    14536. $this->wsdlFile = $this->endpoint;
    14537. -
    14538. $this->wsdl = null;
    14539. -
    14540. $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
    14541. -
    14542. }
    14543. -
    14544. $this->endpointType = 'wsdl';
    14545. -
    14546. } else {
    14547. -
    14548. $this->debug("instantiate SOAP with endpoint at $endpoint");
    14549. -
    14550. $this->endpointType = 'soap';
    14551. -
    14552. }
    14553. -
    14554. }
    14555. -
    14556.  
    14557. -
    14558. /**
    14559. -
    14560. * calls method, returns PHP native type
    14561. -
    14562. *
    14563. -
    14564. * @param string $operation SOAP server URL or path
    14565. -
    14566. * @param mixed $params An array, associative or simple, of the parameters
    14567. -
    14568. * for the method call, or a string that is the XML
    14569. -
    14570. * for the call. For rpc style, this call will
    14571. -
    14572. * wrap the XML in a tag named after the method, as
    14573. -
    14574. * well as the SOAP Envelope and Body. For document
    14575. -
    14576. * style, this will only wrap with the Envelope and Body.
    14577. -
    14578. * IMPORTANT: when using an array with document style,
    14579. -
    14580. * in which case there
    14581. -
    14582. * is really one parameter, the root of the fragment
    14583. -
    14584. * used in the call, which encloses what programmers
    14585. -
    14586. * normally think of parameters. A parameter array
    14587. -
    14588. * *must* include the wrapper.
    14589. -
    14590. * @param string $namespace optional method namespace (WSDL can override)
    14591. -
    14592. * @param string $soapAction optional SOAPAction value (WSDL can override)
    14593. -
    14594. * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
    14595. -
    14596. * @param boolean $rpcParams optional (no longer used)
    14597. -
    14598. * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
    14599. -
    14600. * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
    14601. -
    14602. * @return mixed response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors
    14603. -
    14604. * @access public
    14605. -
    14606. */
    14607. -
    14608. function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
    14609. -
    14610. $this->operation = $operation;
    14611. -
    14612. $this->fault = false;
    14613. -
    14614. $this->setError('');
    14615. -
    14616. $this->request = '';
    14617. -
    14618. $this->response = '';
    14619. -
    14620. $this->responseData = '';
    14621. -
    14622. $this->faultstring = '';
    14623. -
    14624. $this->faultcode = '';
    14625. -
    14626. $this->opData = array();
    14627. -
    14628. -
    14629. $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
    14630. -
    14631. $this->appendDebug('params=' . $this->varDump($params));
    14632. -
    14633. $this->appendDebug('headers=' . $this->varDump($headers));
    14634. -
    14635. if ($headers) {
    14636. -
    14637. $this->requestHeaders = $headers;
    14638. -
    14639. }
    14640. -
    14641. if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
    14642. -
    14643. $this->loadWSDL();
    14644. -
    14645. if ($this->getError())
    14646. -
    14647. return false;
    14648. -
    14649. }
    14650. -
    14651. // serialize parameters
    14652. -
    14653. if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
    14654. -
    14655. // use WSDL for operation
    14656. -
    14657. $this->opData = $opData;
    14658. -
    14659. $this->debug("found operation");
    14660. -
    14661. $this->appendDebug('opData=' . $this->varDump($opData));
    14662. -
    14663. if (isset($opData['soapAction'])) {
    14664. -
    14665. $soapAction = $opData['soapAction'];
    14666. -
    14667. }
    14668. -
    14669. if (! $this->forceEndpoint) {
    14670. -
    14671. $this->endpoint = $opData['endpoint'];
    14672. -
    14673. } else {
    14674. -
    14675. $this->endpoint = $this->forceEndpoint;
    14676. -
    14677. }
    14678. -
    14679. $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
    14680. -
    14681. $style = $opData['style'];
    14682. -
    14683. $use = $opData['input']['use'];
    14684. -
    14685. // add ns to ns array
    14686. -
    14687. if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
    14688. -
    14689. $nsPrefix = 'ns' . rand(1000, 9999);
    14690. -
    14691. $this->wsdl->namespaces[$nsPrefix] = $namespace;
    14692. -
    14693. }
    14694. -
    14695. $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
    14696. -
    14697. // serialize payload
    14698. -
    14699. if (is_string($params)) {
    14700. -
    14701. $this->debug("serializing param string for WSDL operation $operation");
    14702. -
    14703. $payload = $params;
    14704. -
    14705. } elseif (is_array($params)) {
    14706. -
    14707. $this->debug("serializing param array for WSDL operation $operation");
    14708. -
    14709. $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
    14710. -
    14711. } else {
    14712. -
    14713. $this->debug('params must be array or string');
    14714. -
    14715. $this->setError('params must be array or string');
    14716. -
    14717. return false;
    14718. -
    14719. }
    14720. -
    14721. $usedNamespaces = $this->wsdl->usedNamespaces;
    14722. -
    14723. if (isset($opData['input']['encodingStyle'])) {
    14724. -
    14725. $encodingStyle = $opData['input']['encodingStyle'];
    14726. -
    14727. } else {
    14728. -
    14729. $encodingStyle = '';
    14730. -
    14731. }
    14732. -
    14733. $this->appendDebug($this->wsdl->getDebug());
    14734. -
    14735. $this->wsdl->clearDebug();
    14736. -
    14737. if ($errstr = $this->wsdl->getError()) {
    14738. -
    14739. $this->debug('got wsdl error: '.$errstr);
    14740. -
    14741. $this->setError('wsdl error: '.$errstr);
    14742. -
    14743. return false;
    14744. -
    14745. }
    14746. -
    14747. } elseif($this->endpointType == 'wsdl') {
    14748. -
    14749. // operation not in WSDL
    14750. -
    14751. $this->appendDebug($this->wsdl->getDebug());
    14752. -
    14753. $this->wsdl->clearDebug();
    14754. -
    14755. $this->setError('operation '.$operation.' not present in WSDL.');
    14756. -
    14757. $this->debug("operation '$operation' not present in WSDL.");
    14758. -
    14759. return false;
    14760. -
    14761. } else {
    14762. -
    14763. // no WSDL
    14764. -
    14765. //$this->namespaces['ns1'] = $namespace;
    14766. -
    14767. $nsPrefix = 'ns' . rand(1000, 9999);
    14768. -
    14769. // serialize
    14770. -
    14771. $payload = '';
    14772. -
    14773. if (is_string($params)) {
    14774. -
    14775. $this->debug("serializing param string for operation $operation");
    14776. -
    14777. $payload = $params;
    14778. -
    14779. } elseif (is_array($params)) {
    14780. -
    14781. $this->debug("serializing param array for operation $operation");
    14782. -
    14783. foreach($params as $k => $v){
    14784. -
    14785. $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
    14786. -
    14787. }
    14788. -
    14789. } else {
    14790. -
    14791. $this->debug('params must be array or string');
    14792. -
    14793. $this->setError('params must be array or string');
    14794. -
    14795. return false;
    14796. -
    14797. }
    14798. -
    14799. $usedNamespaces = array();
    14800. -
    14801. if ($use == 'encoded') {
    14802. -
    14803. $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
    14804. -
    14805. } else {
    14806. -
    14807. $encodingStyle = '';
    14808. -
    14809. }
    14810. -
    14811. }
    14812. -
    14813. // wrap RPC calls with method element
    14814. -
    14815. if ($style == 'rpc') {
    14816. -
    14817. if ($use == 'literal') {
    14818. -
    14819. $this->debug("wrapping RPC request with literal method element");
    14820. -
    14821. if ($namespace) {
    14822. -
    14823. // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace
    14824. -
    14825. $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
    14826. -
    14827. $payload .
    14828. -
    14829. "</$nsPrefix:$operation>";
    14830. -
    14831. } else {
    14832. -
    14833. $payload = "<$operation>" . $payload . "</$operation>";
    14834. -
    14835. }
    14836. -
    14837. } else {
    14838. -
    14839. $this->debug("wrapping RPC request with encoded method element");
    14840. -
    14841. if ($namespace) {
    14842. -
    14843. $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
    14844. -
    14845. $payload .
    14846. -
    14847. "</$nsPrefix:$operation>";
    14848. -
    14849. } else {
    14850. -
    14851. $payload = "<$operation>" .
    14852. -
    14853. $payload .
    14854. -
    14855. "</$operation>";
    14856. -
    14857. }
    14858. -
    14859. }
    14860. -
    14861. }
    14862. -
    14863. // serialize envelope
    14864. -
    14865. $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
    14866. -
    14867. $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
    14868. -
    14869. $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
    14870. -
    14871. // send
    14872. -
    14873. $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
    14874. -
    14875. if($errstr = $this->getError()){
    14876. -
    14877. $this->debug('Error: '.$errstr);
    14878. -
    14879. return false;
    14880. -
    14881. } else {
    14882. -
    14883. $this->return = $return;
    14884. -
    14885. $this->debug('sent message successfully and got a(n) '.gettype($return));
    14886. -
    14887. $this->appendDebug('return=' . $this->varDump($return));
    14888. -
    14889. -
    14890. // fault?
    14891. -
    14892. if(is_array($return) && isset($return['faultcode'])){
    14893. -
    14894. $this->debug('got fault');
    14895. -
    14896. $this->setError($return['faultcode'].': '.$return['faultstring']);
    14897. -
    14898. $this->fault = true;
    14899. -
    14900. foreach($return as $k => $v){
    14901. -
    14902. $this->$k = $v;
    14903. -
    14904. $this->debug("$k = $v<br>");
    14905. -
    14906. }
    14907. -
    14908. return $return;
    14909. -
    14910. } elseif ($style == 'document') {
    14911. -
    14912. // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
    14913. -
    14914. // we are only going to return the first part here...sorry about that
    14915. -
    14916. return $return;
    14917. -
    14918. } else {
    14919. -
    14920. // array of return values
    14921. -
    14922. if(is_array($return)){
    14923. -
    14924. // multiple 'out' parameters, which we return wrapped up
    14925. -
    14926. // in the array
    14927. -
    14928. if(sizeof($return) > 1){
    14929. -
    14930. return $return;
    14931. -
    14932. }
    14933. -
    14934. // single 'out' parameter (normally the return value)
    14935. -
    14936. $return = array_shift($return);
    14937. -
    14938. $this->debug('return shifted value: ');
    14939. -
    14940. $this->appendDebug($this->varDump($return));
    14941. -
    14942. return $return;
    14943. -
    14944. // nothing returned (ie, echoVoid)
    14945. -
    14946. } else {
    14947. -
    14948. return "";
    14949. -
    14950. }
    14951. -
    14952. }
    14953. -
    14954. }
    14955. -
    14956. }
    14957. -
    14958.  
    14959. -
    14960. /**
    14961. -
    14962. * check WSDL passed as an instance or pulled from an endpoint
    14963. -
    14964. *
    14965. -
    14966. * @access private
    14967. -
    14968. */
    14969. -
    14970. function checkWSDL() {
    14971. -
    14972. $this->appendDebug($this->wsdl->getDebug());
    14973. -
    14974. $this->wsdl->clearDebug();
    14975. -
    14976. $this->debug('checkWSDL');
    14977. -
    14978. // catch errors
    14979. -
    14980. if ($errstr = $this->wsdl->getError()) {
    14981. -
    14982. $this->appendDebug($this->wsdl->getDebug());
    14983. -
    14984. $this->wsdl->clearDebug();
    14985. -
    14986. $this->debug('got wsdl error: '.$errstr);
    14987. -
    14988. $this->setError('wsdl error: '.$errstr);
    14989. -
    14990. } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) {
    14991. -
    14992. $this->appendDebug($this->wsdl->getDebug());
    14993. -
    14994. $this->wsdl->clearDebug();
    14995. -
    14996. $this->bindingType = 'soap';
    14997. -
    14998. $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
    14999. -
    15000. } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) {
    15001. -
    15002. $this->appendDebug($this->wsdl->getDebug());
    15003. -
    15004. $this->wsdl->clearDebug();
    15005. -
    15006. $this->bindingType = 'soap12';
    15007. -
    15008. $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
    15009. -
    15010. $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
    15011. -
    15012. } else {
    15013. -
    15014. $this->appendDebug($this->wsdl->getDebug());
    15015. -
    15016. $this->wsdl->clearDebug();
    15017. -
    15018. $this->debug('getOperations returned false');
    15019. -
    15020. $this->setError('no operations defined in the WSDL document!');
    15021. -
    15022. }
    15023. -
    15024. }
    15025. -
    15026.  
    15027. -
    15028. /**
    15029. -
    15030. * instantiate wsdl object and parse wsdl file
    15031. -
    15032. *
    15033. -
    15034. * @access public
    15035. -
    15036. */
    15037. -
    15038. function loadWSDL() {
    15039. -
    15040. $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
    15041. -
    15042. $this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
    15043. -
    15044. $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
    15045. -
    15046. $this->wsdl->fetchWSDL($this->wsdlFile);
    15047. -
    15048. $this->checkWSDL();
    15049. -
    15050. }
    15051. -
    15052.  
    15053. -
    15054. /**
    15055. -
    15056. * get available data pertaining to an operation
    15057. -
    15058. *
    15059. -
    15060. * @param string $operation operation name
    15061. -
    15062. * @return array array of data pertaining to the operation
    15063. -
    15064. * @access public
    15065. -
    15066. */
    15067. -
    15068. function getOperationData($operation){
    15069. -
    15070. if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
    15071. -
    15072. $this->loadWSDL();
    15073. -
    15074. if ($this->getError())
    15075. -
    15076. return false;
    15077. -
    15078. }
    15079. -
    15080. if(isset($this->operations[$operation])){
    15081. -
    15082. return $this->operations[$operation];
    15083. -
    15084. }
    15085. -
    15086. $this->debug("No data for operation: $operation");
    15087. -
    15088. }
    15089. -
    15090.  
    15091. -
    15092. /**
    15093. -
    15094. * send the SOAP message
    15095. -
    15096. *
    15097. -
    15098. * Note: if the operation has multiple return values
    15099. -
    15100. * the return value of this method will be an array
    15101. -
    15102. * of those values.
    15103. -
    15104. *
    15105. -
    15106. * @param string $msg a SOAPx4 soapmsg object
    15107. -
    15108. * @param string $soapaction SOAPAction value
    15109. -
    15110. * @param integer $timeout set connection timeout in seconds
    15111. -
    15112. * @param integer $response_timeout set response timeout in seconds
    15113. -
    15114. * @return mixed native PHP types.
    15115. -
    15116. * @access private
    15117. -
    15118. */
    15119. -
    15120. function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
    15121. -
    15122. $this->checkCookies();
    15123. -
    15124. // detect transport
    15125. -
    15126. switch(true){
    15127. -
    15128. // http(s)
    15129. -
    15130. case preg_match('/^http/',$this->endpoint):
    15131. -
    15132. $this->debug('transporting via HTTP');
    15133. -
    15134. if($this->persistentConnection == true && is_object($this->persistentConnection)){
    15135. -
    15136. $http =& $this->persistentConnection;
    15137. -
    15138. } else {
    15139. -
    15140. $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
    15141. -
    15142. if ($this->persistentConnection) {
    15143. -
    15144. $http->usePersistentConnection();
    15145. -
    15146. }
    15147. -
    15148. }
    15149. -
    15150. $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
    15151. -
    15152. $http->setSOAPAction($soapaction);
    15153. -
    15154. if($this->proxyhost && $this->proxyport){
    15155. -
    15156. $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
    15157. -
    15158. }
    15159. -
    15160. if($this->authtype != '') {
    15161. -
    15162. $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
    15163. -
    15164. }
    15165. -
    15166. if($this->http_encoding != ''){
    15167. -
    15168. $http->setEncoding($this->http_encoding);
    15169. -
    15170. }
    15171. -
    15172. $this->debug('sending message, length='.strlen($msg));
    15173. -
    15174. if(preg_match('/^http:/',$this->endpoint)){
    15175. -
    15176. //if(strpos($this->endpoint,'http:')){
    15177. -
    15178. $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
    15179. -
    15180. } elseif(preg_match('/^https/',$this->endpoint)){
    15181. -
    15182. //} elseif(strpos($this->endpoint,'https:')){
    15183. -
    15184. //if(phpversion() == '4.3.0-dev'){
    15185. -
    15186. //$response = $http->send($msg,$timeout,$response_timeout);
    15187. -
    15188. //$this->request = $http->outgoing_payload;
    15189. -
    15190. //$this->response = $http->incoming_payload;
    15191. -
    15192. //} else
    15193. -
    15194. $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
    15195. -
    15196. } else {
    15197. -
    15198. $this->setError('no http/s in endpoint url');
    15199. -
    15200. }
    15201. -
    15202. $this->request = $http->outgoing_payload;
    15203. -
    15204. $this->response = $http->incoming_payload;
    15205. -
    15206. $this->appendDebug($http->getDebug());
    15207. -
    15208. $this->UpdateCookies($http->incoming_cookies);
    15209. -
    15210.  
    15211. -
    15212. // save transport object if using persistent connections
    15213. -
    15214. if ($this->persistentConnection) {
    15215. -
    15216. $http->clearDebug();
    15217. -
    15218. if (!is_object($this->persistentConnection)) {
    15219. -
    15220. $this->persistentConnection = $http;
    15221. -
    15222. }
    15223. -
    15224. }
    15225. -
    15226. -
    15227. if($err = $http->getError()){
    15228. -
    15229. $this->setError('HTTP Error: '.$err);
    15230. -
    15231. return false;
    15232. -
    15233. } elseif($this->getError()){
    15234. -
    15235. return false;
    15236. -
    15237. } else {
    15238. -
    15239. $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
    15240. -
    15241. return $this->parseResponse($http->incoming_headers, $this->responseData);
    15242. -
    15243. }
    15244. -
    15245. break;
    15246. -
    15247. default:
    15248. -
    15249. $this->setError('no transport found, or selected transport is not yet supported!');
    15250. -
    15251. return false;
    15252. -
    15253. break;
    15254. -
    15255. }
    15256. -
    15257. }
    15258. -
    15259.  
    15260. -
    15261. /**
    15262. -
    15263. * processes SOAP message returned from server
    15264. -
    15265. *
    15266. -
    15267. * @param array $headers The HTTP headers
    15268. -
    15269. * @param string $data unprocessed response data from server
    15270. -
    15271. * @return mixed value of the message, decoded into a PHP type
    15272. -
    15273. * @access private
    15274. -
    15275. */
    15276. -
    15277. function parseResponse($headers, $data) {
    15278. -
    15279. $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
    15280. -
    15281. $this->appendDebug($this->varDump($headers));
    15282. -
    15283. if (!isset($headers['content-type'])) {
    15284. -
    15285. $this->setError('Response not of type text/xml (no content-type header)');
    15286. -
    15287. return false;
    15288. -
    15289. }
    15290. -
    15291. if (!strstr($headers['content-type'], 'text/xml')) {
    15292. -
    15293. $this->setError('Response not of type text/xml: ' . $headers['content-type']);
    15294. -
    15295. return false;
    15296. -
    15297. }
    15298. -
    15299. if (strpos($headers['content-type'], '=')) {
    15300. -
    15301. $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
    15302. -
    15303. $this->debug('Got response encoding: ' . $enc);
    15304. -
    15305. if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
    15306. -
    15307. $this->xml_encoding = strtoupper($enc);
    15308. -
    15309. } else {
    15310. -
    15311. $this->xml_encoding = 'US-ASCII';
    15312. -
    15313. }
    15314. -
    15315. } else {
    15316. -
    15317. // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
    15318. -
    15319. $this->xml_encoding = 'ISO-8859-1';
    15320. -
    15321. }
    15322. -
    15323. $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
    15324. -
    15325. $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
    15326. -
    15327. // add parser debug data to our debug
    15328. -
    15329. $this->appendDebug($parser->getDebug());
    15330. -
    15331. // if parse errors
    15332. -
    15333. if($errstr = $parser->getError()){
    15334. -
    15335. $this->setError( $errstr);
    15336. -
    15337. // destroy the parser object
    15338. -
    15339. unset($parser);
    15340. -
    15341. return false;
    15342. -
    15343. } else {
    15344. -
    15345. // get SOAP headers
    15346. -
    15347. $this->responseHeaders = $parser->getHeaders();
    15348. -
    15349. // get SOAP headers
    15350. -
    15351. $this->responseHeader = $parser->get_soapheader();
    15352. -
    15353. // get decoded message
    15354. -
    15355. $return = $parser->get_soapbody();
    15356. -
    15357. // add document for doclit support
    15358. -
    15359. $this->document = $parser->document;
    15360. -
    15361. // destroy the parser object
    15362. -
    15363. unset($parser);
    15364. -
    15365. // return decode message
    15366. -
    15367. return $return;
    15368. -
    15369. }
    15370. -
    15371. }
    15372. -
    15373.  
    15374. -
    15375. /**
    15376. -
    15377. * sets user-specified cURL options
    15378. -
    15379. *
    15380. -
    15381. * @param mixed $option The cURL option (always integer?)
    15382. -
    15383. * @param mixed $value The cURL option value
    15384. -
    15385. * @access public
    15386. -
    15387. */
    15388. -
    15389. function setCurlOption($option, $value) {
    15390. -
    15391. $this->debug("setCurlOption option=$option, value=");
    15392. -
    15393. $this->appendDebug($this->varDump($value));
    15394. -
    15395. $this->curl_options[$option] = $value;
    15396. -
    15397. }
    15398. -
    15399.  
    15400. -
    15401. /**
    15402. -
    15403. * sets the SOAP endpoint, which can override WSDL
    15404. -
    15405. *
    15406. -
    15407. * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override
    15408. -
    15409. * @access public
    15410. -
    15411. */
    15412. -
    15413. function setEndpoint($endpoint) {
    15414. -
    15415. $this->debug("setEndpoint(\"$endpoint\")");
    15416. -
    15417. $this->forceEndpoint = $endpoint;
    15418. -
    15419. }
    15420. -
    15421.  
    15422. -
    15423. /**
    15424. -
    15425. * set the SOAP headers
    15426. -
    15427. *
    15428. -
    15429. * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
    15430. -
    15431. * @access public
    15432. -
    15433. */
    15434. -
    15435. function setHeaders($headers){
    15436. -
    15437. $this->debug("setHeaders headers=");
    15438. -
    15439. $this->appendDebug($this->varDump($headers));
    15440. -
    15441. $this->requestHeaders = $headers;
    15442. -
    15443. }
    15444. -
    15445.  
    15446. -
    15447. /**
    15448. -
    15449. * get the SOAP response headers (namespace resolution incomplete)
    15450. -
    15451. *
    15452. -
    15453. * @return string
    15454. -
    15455. * @access public
    15456. -
    15457. */
    15458. -
    15459. function getHeaders(){
    15460. -
    15461. return $this->responseHeaders;
    15462. -
    15463. }
    15464. -
    15465.  
    15466. -
    15467. /**
    15468. -
    15469. * get the SOAP response Header (parsed)
    15470. -
    15471. *
    15472. -
    15473. * @return mixed
    15474. -
    15475. * @access public
    15476. -
    15477. */
    15478. -
    15479. function getHeader(){
    15480. -
    15481. return $this->responseHeader;
    15482. -
    15483. }
    15484. -
    15485.  
    15486. -
    15487. /**
    15488. -
    15489. * set proxy info here
    15490. -
    15491. *
    15492. -
    15493. * @param string $proxyhost
    15494. -
    15495. * @param string $proxyport
    15496. -
    15497. * @param string $proxyusername
    15498. -
    15499. * @param string $proxypassword
    15500. -
    15501. * @access public
    15502. -
    15503. */
    15504. -
    15505. function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
    15506. -
    15507. $this->proxyhost = $proxyhost;
    15508. -
    15509. $this->proxyport = $proxyport;
    15510. -
    15511. $this->proxyusername = $proxyusername;
    15512. -
    15513. $this->proxypassword = $proxypassword;
    15514. -
    15515. }
    15516. -
    15517.  
    15518. -
    15519. /**
    15520. -
    15521. * if authenticating, set user credentials here
    15522. -
    15523. *
    15524. -
    15525. * @param string $username
    15526. -
    15527. * @param string $password
    15528. -
    15529. * @param string $authtype (basic|digest|certificate|ntlm)
    15530. -
    15531. * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
    15532. -
    15533. * @access public
    15534. -
    15535. */
    15536. -
    15537. function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
    15538. -
    15539. $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
    15540. -
    15541. $this->appendDebug($this->varDump($certRequest));
    15542. -
    15543. $this->username = $username;
    15544. -
    15545. $this->password = $password;
    15546. -
    15547. $this->authtype = $authtype;
    15548. -
    15549. $this->certRequest = $certRequest;
    15550. -
    15551. }
    15552. -
    15553. -
    15554. /**
    15555. -
    15556. * use HTTP encoding
    15557. -
    15558. *
    15559. -
    15560. * @param string $enc HTTP encoding
    15561. -
    15562. * @access public
    15563. -
    15564. */
    15565. -
    15566. function setHTTPEncoding($enc='gzip, deflate'){
    15567. -
    15568. $this->debug("setHTTPEncoding(\"$enc\")");
    15569. -
    15570. $this->http_encoding = $enc;
    15571. -
    15572. }
    15573. -
    15574. -
    15575. /**
    15576. -
    15577. * Set whether to try to use cURL connections if possible
    15578. -
    15579. *
    15580. -
    15581. * @param boolean $use Whether to try to use cURL
    15582. -
    15583. * @access public
    15584. -
    15585. */
    15586. -
    15587. function setUseCURL($use) {
    15588. -
    15589. $this->debug("setUseCURL($use)");
    15590. -
    15591. $this->use_curl = $use;
    15592. -
    15593. }
    15594. -
    15595.  
    15596. -
    15597. /**
    15598. -
    15599. * use HTTP persistent connections if possible
    15600. -
    15601. *
    15602. -
    15603. * @access public
    15604. -
    15605. */
    15606. -
    15607. function useHTTPPersistentConnection(){
    15608. -
    15609. $this->debug("useHTTPPersistentConnection");
    15610. -
    15611. $this->persistentConnection = true;
    15612. -
    15613. }
    15614. -
    15615. -
    15616. /**
    15617. -
    15618. * gets the default RPC parameter setting.
    15619. -
    15620. * If true, default is that call params are like RPC even for document style.
    15621. -
    15622. * Each call() can override this value.
    15623. -
    15624. *
    15625. -
    15626. * This is no longer used.
    15627. -
    15628. *
    15629. -
    15630. * @return boolean
    15631. -
    15632. * @access public
    15633. -
    15634. * @deprecated
    15635. -
    15636. */
    15637. -
    15638. function getDefaultRpcParams() {
    15639. -
    15640. return $this->defaultRpcParams;
    15641. -
    15642. }
    15643. -
    15644.  
    15645. -
    15646. /**
    15647. -
    15648. * sets the default RPC parameter setting.
    15649. -
    15650. * If true, default is that call params are like RPC even for document style
    15651. -
    15652. * Each call() can override this value.
    15653. -
    15654. *
    15655. -
    15656. * This is no longer used.
    15657. -
    15658. *
    15659. -
    15660. * @param boolean $rpcParams
    15661. -
    15662. * @access public
    15663. -
    15664. * @deprecated
    15665. -
    15666. */
    15667. -
    15668. function setDefaultRpcParams($rpcParams) {
    15669. -
    15670. $this->defaultRpcParams = $rpcParams;
    15671. -
    15672. }
    15673. -
    15674. -
    15675. /**
    15676. -
    15677. * dynamically creates an instance of a proxy class,
    15678. -
    15679. * allowing user to directly call methods from wsdl
    15680. -
    15681. *
    15682. -
    15683. * @return object soap_proxy object
    15684. -
    15685. * @access public
    15686. -
    15687. */
    15688. -
    15689. function getProxy() {
    15690. -
    15691. $r = rand();
    15692. -
    15693. $evalStr = $this->_getProxyClassCode($r);
    15694. -
    15695. //$this->debug("proxy class: $evalStr");
    15696. -
    15697. if ($this->getError()) {
    15698. -
    15699. $this->debug("Error from _getProxyClassCode, so return NULL");
    15700. -
    15701. return null;
    15702. -
    15703. }
    15704. -
    15705. // eval the class
    15706. -
    15707. eval($evalStr);
    15708. -
    15709. // instantiate proxy object
    15710. -
    15711. eval("\$proxy = new nusoap_proxy_$r('');");
    15712. -
    15713. // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
    15714. -
    15715. $proxy->endpointType = 'wsdl';
    15716. -
    15717. $proxy->wsdlFile = $this->wsdlFile;
    15718. -
    15719. $proxy->wsdl = $this->wsdl;
    15720. -
    15721. $proxy->operations = $this->operations;
    15722. -
    15723. $proxy->defaultRpcParams = $this->defaultRpcParams;
    15724. -
    15725. // transfer other state
    15726. -
    15727. $proxy->soap_defencoding = $this->soap_defencoding;
    15728. -
    15729. $proxy->username = $this->username;
    15730. -
    15731. $proxy->password = $this->password;
    15732. -
    15733. $proxy->authtype = $this->authtype;
    15734. -
    15735. $proxy->certRequest = $this->certRequest;
    15736. -
    15737. $proxy->requestHeaders = $this->requestHeaders;
    15738. -
    15739. $proxy->endpoint = $this->endpoint;
    15740. -
    15741. $proxy->forceEndpoint = $this->forceEndpoint;
    15742. -
    15743. $proxy->proxyhost = $this->proxyhost;
    15744. -
    15745. $proxy->proxyport = $this->proxyport;
    15746. -
    15747. $proxy->proxyusername = $this->proxyusername;
    15748. -
    15749. $proxy->proxypassword = $this->proxypassword;
    15750. -
    15751. $proxy->http_encoding = $this->http_encoding;
    15752. -
    15753. $proxy->timeout = $this->timeout;
    15754. -
    15755. $proxy->response_timeout = $this->response_timeout;
    15756. -
    15757. $proxy->persistentConnection = &$this->persistentConnection;
    15758. -
    15759. $proxy->decode_utf8 = $this->decode_utf8;
    15760. -
    15761. $proxy->curl_options = $this->curl_options;
    15762. -
    15763. $proxy->bindingType = $this->bindingType;
    15764. -
    15765. $proxy->use_curl = $this->use_curl;
    15766. -
    15767. return $proxy;
    15768. -
    15769. }
    15770. -
    15771.  
    15772. -
    15773. /**
    15774. -
    15775. * dynamically creates proxy class code
    15776. -
    15777. *
    15778. -
    15779. * @return string PHP/NuSOAP code for the proxy class
    15780. -
    15781. * @access private
    15782. -
    15783. */
    15784. -
    15785. function _getProxyClassCode($r) {
    15786. -
    15787. $this->debug("in getProxy endpointType=$this->endpointType");
    15788. -
    15789. $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
    15790. -
    15791. if ($this->endpointType != 'wsdl') {
    15792. -
    15793. $evalStr = 'A proxy can only be created for a WSDL client';
    15794. -
    15795. $this->setError($evalStr);
    15796. -
    15797. $evalStr = "echo \"$evalStr\";";
    15798. -
    15799. return $evalStr;
    15800. -
    15801. }
    15802. -
    15803. if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
    15804. -
    15805. $this->loadWSDL();
    15806. -
    15807. if ($this->getError()) {
    15808. -
    15809. return "echo \"" . $this->getError() . "\";";
    15810. -
    15811. }
    15812. -
    15813. }
    15814. -
    15815. $evalStr = '';
    15816. -
    15817. foreach ($this->operations as $operation => $opData) {
    15818. -
    15819. if ($operation != '') {
    15820. -
    15821. // create param string and param comment string
    15822. -
    15823. if (sizeof($opData['input']['parts']) > 0) {
    15824. -
    15825. $paramStr = '';
    15826. -
    15827. $paramArrayStr = '';
    15828. -
    15829. $paramCommentStr = '';
    15830. -
    15831. foreach ($opData['input']['parts'] as $name => $type) {
    15832. -
    15833. $paramStr .= "\$$name, ";
    15834. -
    15835. $paramArrayStr .= "'$name' => \$$name, ";
    15836. -
    15837. $paramCommentStr .= "$type \$$name, ";
    15838. -
    15839. }
    15840. -
    15841. $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
    15842. -
    15843. $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
    15844. -
    15845. $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
    15846. -
    15847. } else {
    15848. -
    15849. $paramStr = '';
    15850. -
    15851. $paramArrayStr = '';
    15852. -
    15853. $paramCommentStr = 'void';
    15854. -
    15855. }
    15856. -
    15857. $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
    15858. -
    15859. $evalStr .= "// $paramCommentStr
    15860. -
    15861. function " . str_replace('.', '__', $operation) . "($paramStr) {
    15862. -
    15863. \$params = array($paramArrayStr);
    15864. -
    15865. return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
    15866. -
    15867. }
    15868. -
    15869. ";
    15870. -
    15871. unset($paramStr);
    15872. -
    15873. unset($paramCommentStr);
    15874. -
    15875. }
    15876. -
    15877. }
    15878. -
    15879. $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
    15880. -
    15881. '.$evalStr.'
    15882. -
    15883. }';
    15884. -
    15885. return $evalStr;
    15886. -
    15887. }
    15888. -
    15889.  
    15890. -
    15891. /**
    15892. -
    15893. * dynamically creates proxy class code
    15894. -
    15895. *
    15896. -
    15897. * @return string PHP/NuSOAP code for the proxy class
    15898. -
    15899. * @access public
    15900. -
    15901. */
    15902. -
    15903. function getProxyClassCode() {
    15904. -
    15905. $r = rand();
    15906. -
    15907. return $this->_getProxyClassCode($r);
    15908. -
    15909. }
    15910. -
    15911.  
    15912. -
    15913. /**
    15914. -
    15915. * gets the HTTP body for the current request.
    15916. -
    15917. *
    15918. -
    15919. * @param string $soapmsg The SOAP payload
    15920. -
    15921. * @return string The HTTP body, which includes the SOAP payload
    15922. -
    15923. * @access private
    15924. -
    15925. */
    15926. -
    15927. function getHTTPBody($soapmsg) {
    15928. -
    15929. return $soapmsg;
    15930. -
    15931. }
    15932. -
    15933. -
    15934. /**
    15935. -
    15936. * gets the HTTP content type for the current request.
    15937. -
    15938. *
    15939. -
    15940. * Note: getHTTPBody must be called before this.
    15941. -
    15942. *
    15943. -
    15944. * @return string the HTTP content type for the current request.
    15945. -
    15946. * @access private
    15947. -
    15948. */
    15949. -
    15950. function getHTTPContentType() {
    15951. -
    15952. return 'text/xml';
    15953. -
    15954. }
    15955. -
    15956. -
    15957. /**
    15958. -
    15959. * gets the HTTP content type charset for the current request.
    15960. -
    15961. * returns false for non-text content types.
    15962. -
    15963. *
    15964. -
    15965. * Note: getHTTPBody must be called before this.
    15966. -
    15967. *
    15968. -
    15969. * @return string the HTTP content type charset for the current request.
    15970. -
    15971. * @access private
    15972. -
    15973. */
    15974. -
    15975. function getHTTPContentTypeCharset() {
    15976. -
    15977. return $this->soap_defencoding;
    15978. -
    15979. }
    15980. -
    15981.  
    15982. -
    15983. /*
    15984. -
    15985. * whether or not parser should decode utf8 element content
    15986. -
    15987. *
    15988. -
    15989. * @return always returns true
    15990. -
    15991. * @access public
    15992. -
    15993. */
    15994. -
    15995. function decodeUTF8($bool){
    15996. -
    15997. $this->decode_utf8 = $bool;
    15998. -
    15999. return true;
    16000. -
    16001. }
    16002. -
    16003.  
    16004. -
    16005. /**
    16006. -
    16007. * adds a new Cookie into $this->cookies array
    16008. -
    16009. *
    16010. -
    16011. * @param string $name Cookie Name
    16012. -
    16013. * @param string $value Cookie Value
    16014. -
    16015. * @return boolean if cookie-set was successful returns true, else false
    16016. -
    16017. * @access public
    16018. -
    16019. */
    16020. -
    16021. function setCookie($name, $value) {
    16022. -
    16023. if (strlen($name) == 0) {
    16024. -
    16025. return false;
    16026. -
    16027. }
    16028. -
    16029. $this->cookies[] = array('name' => $name, 'value' => $value);
    16030. -
    16031. return true;
    16032. -
    16033. }
    16034. -
    16035.  
    16036. -
    16037. /**
    16038. -
    16039. * gets all Cookies
    16040. -
    16041. *
    16042. -
    16043. * @return array with all internal cookies
    16044. -
    16045. * @access public
    16046. -
    16047. */
    16048. -
    16049. function getCookies() {
    16050. -
    16051. return $this->cookies;
    16052. -
    16053. }
    16054. -
    16055.  
    16056. -
    16057. /**
    16058. -
    16059. * checks all Cookies and delete those which are expired
    16060. -
    16061. *
    16062. -
    16063. * @return boolean always return true
    16064. -
    16065. * @access private
    16066. -
    16067. */
    16068. -
    16069. function checkCookies() {
    16070. -
    16071. if (sizeof($this->cookies) == 0) {
    16072. -
    16073. return true;
    16074. -
    16075. }
    16076. -
    16077. $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
    16078. -
    16079. $curr_cookies = $this->cookies;
    16080. -
    16081. $this->cookies = array();
    16082. -
    16083. foreach ($curr_cookies as $cookie) {
    16084. -
    16085. if (! is_array($cookie)) {
    16086. -
    16087. $this->debug('Remove cookie that is not an array');
    16088. -
    16089. continue;
    16090. -
    16091. }
    16092. -
    16093. if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
    16094. -
    16095. if (strtotime($cookie['expires']) > time()) {
    16096. -
    16097. $this->cookies[] = $cookie;
    16098. -
    16099. } else {
    16100. -
    16101. $this->debug('Remove expired cookie ' . $cookie['name']);
    16102. -
    16103. }
    16104. -
    16105. } else {
    16106. -
    16107. $this->cookies[] = $cookie;
    16108. -
    16109. }
    16110. -
    16111. }
    16112. -
    16113. $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
    16114. -
    16115. return true;
    16116. -
    16117. }
    16118. -
    16119.  
    16120. -
    16121. /**
    16122. -
    16123. * updates the current cookies with a new set
    16124. -
    16125. *
    16126. -
    16127. * @param array $cookies new cookies with which to update current ones
    16128. -
    16129. * @return boolean always return true
    16130. -
    16131. * @access private
    16132. -
    16133. */
    16134. -
    16135. function UpdateCookies($cookies) {
    16136. -
    16137. if (sizeof($this->cookies) == 0) {
    16138. -
    16139. // no existing cookies: take whatever is new
    16140. -
    16141. if (sizeof($cookies) > 0) {
    16142. -
    16143. $this->debug('Setting new cookie(s)');
    16144. -
    16145. $this->cookies = $cookies;
    16146. -
    16147. }
    16148. -
    16149. return true;
    16150. -
    16151. }
    16152. -
    16153. if (sizeof($cookies) == 0) {
    16154. -
    16155. // no new cookies: keep what we've got
    16156. -
    16157. return true;
    16158. -
    16159. }
    16160. -
    16161. // merge
    16162. -
    16163. foreach ($cookies as $newCookie) {
    16164. -
    16165. if (!is_array($newCookie)) {
    16166. -
    16167. continue;
    16168. -
    16169. }
    16170. -
    16171. if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
    16172. -
    16173. continue;
    16174. -
    16175. }
    16176. -
    16177. $newName = $newCookie['name'];
    16178. -
    16179.  
    16180. -
    16181. $found = false;
    16182. -
    16183. for ($i = 0; $i < count($this->cookies); $i++) {
    16184. -
    16185. $cookie = $this->cookies[$i];
    16186. -
    16187. if (!is_array($cookie)) {
    16188. -
    16189. continue;
    16190. -
    16191. }
    16192. -
    16193. if (!isset($cookie['name'])) {
    16194. -
    16195. continue;
    16196. -
    16197. }
    16198. -
    16199. if ($newName != $cookie['name']) {
    16200. -
    16201. continue;
    16202. -
    16203. }
    16204. -
    16205. $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
    16206. -
    16207. $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
    16208. -
    16209. if ($newDomain != $domain) {
    16210. -
    16211. continue;
    16212. -
    16213. }
    16214. -
    16215. $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
    16216. -
    16217. $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
    16218. -
    16219. if ($newPath != $path) {
    16220. -
    16221. continue;
    16222. -
    16223. }
    16224. -
    16225. $this->cookies[$i] = $newCookie;
    16226. -
    16227. $found = true;
    16228. -
    16229. $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
    16230. -
    16231. break;
    16232. -
    16233. }
    16234. -
    16235. if (! $found) {
    16236. -
    16237. $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
    16238. -
    16239. $this->cookies[] = $newCookie;
    16240. -
    16241. }
    16242. -
    16243. }
    16244. -
    16245. return true;
    16246. -
    16247. }
    16248. -
    16249. }
    16250. -
    16251.  
    16252. -
    16253. if (!extension_loaded('soap')) {
    16254. -
    16255. /**
    16256. -
    16257. * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
    16258. -
    16259. */
    16260. -
    16261. class soapclient extends nusoap_client {
    16262. -
    16263. }
    16264. -
    16265. }
    16266. -
    16267. ?>
    16268. -
    -
    -

    - Documentation generated on Mon, 26 Apr 2010 16:17:01 -0400 by phpDocumentor 1.3.0RC3 -

    - - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/__filesource/fsource_nusoap__nusoapmime.php.html b/lib/nusoap/docs/docs/__filesource/fsource_nusoap__nusoapmime.php.html deleted file mode 100644 index bb3729a13..000000000 --- a/lib/nusoap/docs/docs/__filesource/fsource_nusoap__nusoapmime.php.html +++ /dev/null @@ -1,521 +0,0 @@ - - - - - - File Source for nusoapmime.php - - - - -

    Source for file nusoapmime.php

    -

    Documentation is available at nusoapmime.php

    -
    -
    1. <?php
    2. -
    3. /*
    4. -
    5. $Id: fsource_nusoap__nusoapmime.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    6. -
    7.  
    8. -
    9. NuSOAP - Web Services Toolkit for PHP
    10. -
    11.  
    12. -
    13. Copyright (c) 2002 NuSphere Corporation
    14. -
    15.  
    16. -
    17. This library is free software; you can redistribute it and/or
    18. -
    19. modify it under the terms of the GNU Lesser General Public
    20. -
    21. License as published by the Free Software Foundation; either
    22. -
    23. version 2.1 of the License, or (at your option) any later version.
    24. -
    25.  
    26. -
    27. This library is distributed in the hope that it will be useful,
    28. -
    29. but WITHOUT ANY WARRANTY; without even the implied warranty of
    30. -
    31. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    32. -
    33. Lesser General Public License for more details.
    34. -
    35.  
    36. -
    37. You should have received a copy of the GNU Lesser General Public
    38. -
    39. License along with this library; if not, write to the Free Software
    40. -
    41. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    42. -
    43.  
    44. -
    45. The NuSOAP project home is:
    46. -
    47. http://sourceforge.net/projects/nusoap/
    48. -
    49.  
    50. -
    51. The primary support for NuSOAP is the mailing list:
    52. -
    53. nusoap-general@lists.sourceforge.net
    54. -
    55.  
    56. -
    57. If you have any questions or comments, please email:
    58. -
    59.  
    60. -
    61. Dietrich Ayala
    62. -
    63. dietrich@ganx4.com
    64. -
    65. http://dietrich.ganx4.com/nusoap
    66. -
    67.  
    68. -
    69. NuSphere Corporation
    70. -
    71. http://www.nusphere.com
    72. -
    73.  
    74. -
    75. */
    76. -
    77.  
    78. -
    79. /*require_once('nusoap.php');*/
    80. -
    81. /* PEAR Mail_MIME library */
    82. -
    83. require_once('Mail/mimeDecode.php');
    84. -
    85. require_once('Mail/mimePart.php');
    86. -
    87.  
    88. -
    89. /**
    90. -
    91. * nusoap_client_mime client supporting MIME attachments defined at
    92. -
    93. * http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
    94. -
    95. *
    96. -
    97. * @author Scott Nichol <snichol@users.sourceforge.net>
    98. -
    99. * @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
    100. -
    101. * @version $Id: fsource_nusoap__nusoapmime.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    102. -
    103. * @access public
    104. -
    105. */
    106. -
    107. class nusoap_client_mime extends nusoap_client {
    108. -
    109. /**
    110. -
    111. * @var array Each array element in the return is an associative array with keys
    112. -
    113. * data, filename, contenttype, cid
    114. -
    115. * @access private
    116. -
    117. */
    118. -
    119. var $requestAttachments = array();
    120. -
    121. /**
    122. -
    123. * @var array Each array element in the return is an associative array with keys
    124. -
    125. * data, filename, contenttype, cid
    126. -
    127. * @access private
    128. -
    129. */
    130. -
    131. var $responseAttachments;
    132. -
    133. /**
    134. -
    135. * @var string
    136. -
    137. * @access private
    138. -
    139. */
    140. -
    141. var $mimeContentType;
    142. -
    143. -
    144. /**
    145. -
    146. * adds a MIME attachment to the current request.
    147. -
    148. *
    149. -
    150. * If the $data parameter contains an empty string, this method will read
    151. -
    152. * the contents of the file named by the $filename parameter.
    153. -
    154. *
    155. -
    156. * If the $cid parameter is false, this method will generate the cid.
    157. -
    158. *
    159. -
    160. * @param string $data The data of the attachment
    161. -
    162. * @param string $filename The filename of the attachment (default is empty string)
    163. -
    164. * @param string $contenttype The MIME Content-Type of the attachment (default is application/octet-stream)
    165. -
    166. * @param string $cid The content-id (cid) of the attachment (default is false)
    167. -
    168. * @return string The content-id (cid) of the attachment
    169. -
    170. * @access public
    171. -
    172. */
    173. -
    174. function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) {
    175. -
    176. if (! $cid) {
    177. -
    178. $cid = md5(uniqid(time()));
    179. -
    180. }
    181. -
    182.  
    183. -
    184. $info['data'] = $data;
    185. -
    186. $info['filename'] = $filename;
    187. -
    188. $info['contenttype'] = $contenttype;
    189. -
    190. $info['cid'] = $cid;
    191. -
    192. -
    193. $this->requestAttachments[] = $info;
    194. -
    195.  
    196. -
    197. return $cid;
    198. -
    199. }
    200. -
    201.  
    202. -
    203. /**
    204. -
    205. * clears the MIME attachments for the current request.
    206. -
    207. *
    208. -
    209. * @access public
    210. -
    211. */
    212. -
    213. function clearAttachments() {
    214. -
    215. $this->requestAttachments = array();
    216. -
    217. }
    218. -
    219.  
    220. -
    221. /**
    222. -
    223. * gets the MIME attachments from the current response.
    224. -
    225. *
    226. -
    227. * Each array element in the return is an associative array with keys
    228. -
    229. * data, filename, contenttype, cid. These keys correspond to the parameters
    230. -
    231. * for addAttachment.
    232. -
    233. *
    234. -
    235. * @return array The attachments.
    236. -
    237. * @access public
    238. -
    239. */
    240. -
    241. function getAttachments() {
    242. -
    243. return $this->responseAttachments;
    244. -
    245. }
    246. -
    247.  
    248. -
    249. /**
    250. -
    251. * gets the HTTP body for the current request.
    252. -
    253. *
    254. -
    255. * @param string $soapmsg The SOAP payload
    256. -
    257. * @return string The HTTP body, which includes the SOAP payload
    258. -
    259. * @access private
    260. -
    261. */
    262. -
    263. function getHTTPBody($soapmsg) {
    264. -
    265. if (count($this->requestAttachments) > 0) {
    266. -
    267. $params['content_type'] = 'multipart/related; type="text/xml"';
    268. -
    269. $mimeMessage = new Mail_mimePart('', $params);
    270. -
    271. unset($params);
    272. -
    273.  
    274. -
    275. $params['content_type'] = 'text/xml';
    276. -
    277. $params['encoding'] = '8bit';
    278. -
    279. $params['charset'] = $this->soap_defencoding;
    280. -
    281. $mimeMessage->addSubpart($soapmsg, $params);
    282. -
    283. -
    284. foreach ($this->requestAttachments as $att) {
    285. -
    286. unset($params);
    287. -
    288.  
    289. -
    290. $params['content_type'] = $att['contenttype'];
    291. -
    292. $params['encoding'] = 'base64';
    293. -
    294. $params['disposition'] = 'attachment';
    295. -
    296. $params['dfilename'] = $att['filename'];
    297. -
    298. $params['cid'] = $att['cid'];
    299. -
    300.  
    301. -
    302. if ($att['data'] == '' && $att['filename'] <> '') {
    303. -
    304. if ($fd = fopen($att['filename'], 'rb')) {
    305. -
    306. $data = fread($fd, filesize($att['filename']));
    307. -
    308. fclose($fd);
    309. -
    310. } else {
    311. -
    312. $data = '';
    313. -
    314. }
    315. -
    316. $mimeMessage->addSubpart($data, $params);
    317. -
    318. } else {
    319. -
    320. $mimeMessage->addSubpart($att['data'], $params);
    321. -
    322. }
    323. -
    324. }
    325. -
    326.  
    327. -
    328. $output = $mimeMessage->encode();
    329. -
    330. $mimeHeaders = $output['headers'];
    331. -
    332. -
    333. foreach ($mimeHeaders as $k => $v) {
    334. -
    335. $this->debug("MIME header $k: $v");
    336. -
    337. if (strtolower($k) == 'content-type') {
    338. -
    339. // PHP header() seems to strip leading whitespace starting
    340. -
    341. // the second line, so force everything to one line
    342. -
    343. $this->mimeContentType = str_replace("\r\n", " ", $v);
    344. -
    345. }
    346. -
    347. }
    348. -
    349. -
    350. return $output['body'];
    351. -
    352. }
    353. -
    354.  
    355. -
    356. return parent::getHTTPBody($soapmsg);
    357. -
    358. }
    359. -
    360. -
    361. /**
    362. -
    363. * gets the HTTP content type for the current request.
    364. -
    365. *
    366. -
    367. * Note: getHTTPBody must be called before this.
    368. -
    369. *
    370. -
    371. * @return string the HTTP content type for the current request.
    372. -
    373. * @access private
    374. -
    375. */
    376. -
    377. function getHTTPContentType() {
    378. -
    379. if (count($this->requestAttachments) > 0) {
    380. -
    381. return $this->mimeContentType;
    382. -
    383. }
    384. -
    385. return parent::getHTTPContentType();
    386. -
    387. }
    388. -
    389. -
    390. /**
    391. -
    392. * gets the HTTP content type charset for the current request.
    393. -
    394. * returns false for non-text content types.
    395. -
    396. *
    397. -
    398. * Note: getHTTPBody must be called before this.
    399. -
    400. *
    401. -
    402. * @return string the HTTP content type charset for the current request.
    403. -
    404. * @access private
    405. -
    406. */
    407. -
    408. function getHTTPContentTypeCharset() {
    409. -
    410. if (count($this->requestAttachments) > 0) {
    411. -
    412. return false;
    413. -
    414. }
    415. -
    416. return parent::getHTTPContentTypeCharset();
    417. -
    418. }
    419. -
    420.  
    421. -
    422. /**
    423. -
    424. * processes SOAP message returned from server
    425. -
    426. *
    427. -
    428. * @param array $headers The HTTP headers
    429. -
    430. * @param string $data unprocessed response data from server
    431. -
    432. * @return mixed value of the message, decoded into a PHP type
    433. -
    434. * @access private
    435. -
    436. */
    437. -
    438. function parseResponse($headers, $data) {
    439. -
    440. $this->debug('Entering parseResponse() for payload of length ' . strlen($data) . ' and type of ' . $headers['content-type']);
    441. -
    442. $this->responseAttachments = array();
    443. -
    444. if (strstr($headers['content-type'], 'multipart/related')) {
    445. -
    446. $this->debug('Decode multipart/related');
    447. -
    448. $input = '';
    449. -
    450. foreach ($headers as $k => $v) {
    451. -
    452. $input .= "$k: $v\r\n";
    453. -
    454. }
    455. -
    456. $params['input'] = $input . "\r\n" . $data;
    457. -
    458. $params['include_bodies'] = true;
    459. -
    460. $params['decode_bodies'] = true;
    461. -
    462. $params['decode_headers'] = true;
    463. -
    464. -
    465. $structure = Mail_mimeDecode::decode($params);
    466. -
    467.  
    468. -
    469. foreach ($structure->parts as $part) {
    470. -
    471. if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) {
    472. -
    473. $this->debug('Have root part of type ' . $part->headers['content-type']);
    474. -
    475. $root = $part->body;
    476. -
    477. $return = parent::parseResponse($part->headers, $part->body);
    478. -
    479. } else {
    480. -
    481. $this->debug('Have an attachment of type ' . $part->headers['content-type']);
    482. -
    483. $info['data'] = $part->body;
    484. -
    485. $info['filename'] = isset($part->d_parameters['filename']) ? $part->d_parameters['filename'] : '';
    486. -
    487. $info['contenttype'] = $part->headers['content-type'];
    488. -
    489. $info['cid'] = $part->headers['content-id'];
    490. -
    491. $this->responseAttachments[] = $info;
    492. -
    493. }
    494. -
    495. }
    496. -
    497. -
    498. if (isset($return)) {
    499. -
    500. $this->responseData = $root;
    501. -
    502. return $return;
    503. -
    504. }
    505. -
    506. -
    507. $this->setError('No root part found in multipart/related content');
    508. -
    509. return '';
    510. -
    511. }
    512. -
    513. $this->debug('Not multipart/related');
    514. -
    515. return parent::parseResponse($headers, $data);
    516. -
    517. }
    518. -
    519. }
    520. -
    521.  
    522. -
    523. /*
    524. -
    525. * For backwards compatiblity, define soapclientmime unless the PHP SOAP extension is loaded.
    526. -
    527. */
    528. -
    529. if (!extension_loaded('soap')) {
    530. -
    531. class soapclientmime extends nusoap_client_mime {
    532. -
    533. }
    534. -
    535. }
    536. -
    537.  
    538. -
    539. /**
    540. -
    541. * nusoap_server_mime server supporting MIME attachments defined at
    542. -
    543. * http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
    544. -
    545. *
    546. -
    547. * @author Scott Nichol <snichol@users.sourceforge.net>
    548. -
    549. * @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
    550. -
    551. * @version $Id: fsource_nusoap__nusoapmime.php.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    552. -
    553. * @access public
    554. -
    555. */
    556. -
    557. class nusoap_server_mime extends nusoap_server {
    558. -
    559. /**
    560. -
    561. * @var array Each array element in the return is an associative array with keys
    562. -
    563. * data, filename, contenttype, cid
    564. -
    565. * @access private
    566. -
    567. */
    568. -
    569. var $requestAttachments = array();
    570. -
    571. /**
    572. -
    573. * @var array Each array element in the return is an associative array with keys
    574. -
    575. * data, filename, contenttype, cid
    576. -
    577. * @access private
    578. -
    579. */
    580. -
    581. var $responseAttachments;
    582. -
    583. /**
    584. -
    585. * @var string
    586. -
    587. * @access private
    588. -
    589. */
    590. -
    591. var $mimeContentType;
    592. -
    593. -
    594. /**
    595. -
    596. * adds a MIME attachment to the current response.
    597. -
    598. *
    599. -
    600. * If the $data parameter contains an empty string, this method will read
    601. -
    602. * the contents of the file named by the $filename parameter.
    603. -
    604. *
    605. -
    606. * If the $cid parameter is false, this method will generate the cid.
    607. -
    608. *
    609. -
    610. * @param string $data The data of the attachment
    611. -
    612. * @param string $filename The filename of the attachment (default is empty string)
    613. -
    614. * @param string $contenttype The MIME Content-Type of the attachment (default is application/octet-stream)
    615. -
    616. * @param string $cid The content-id (cid) of the attachment (default is false)
    617. -
    618. * @return string The content-id (cid) of the attachment
    619. -
    620. * @access public
    621. -
    622. */
    623. -
    624. function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) {
    625. -
    626. if (! $cid) {
    627. -
    628. $cid = md5(uniqid(time()));
    629. -
    630. }
    631. -
    632.  
    633. -
    634. $info['data'] = $data;
    635. -
    636. $info['filename'] = $filename;
    637. -
    638. $info['contenttype'] = $contenttype;
    639. -
    640. $info['cid'] = $cid;
    641. -
    642. -
    643. $this->responseAttachments[] = $info;
    644. -
    645.  
    646. -
    647. return $cid;
    648. -
    649. }
    650. -
    651.  
    652. -
    653. /**
    654. -
    655. * clears the MIME attachments for the current response.
    656. -
    657. *
    658. -
    659. * @access public
    660. -
    661. */
    662. -
    663. function clearAttachments() {
    664. -
    665. $this->responseAttachments = array();
    666. -
    667. }
    668. -
    669.  
    670. -
    671. /**
    672. -
    673. * gets the MIME attachments from the current request.
    674. -
    675. *
    676. -
    677. * Each array element in the return is an associative array with keys
    678. -
    679. * data, filename, contenttype, cid. These keys correspond to the parameters
    680. -
    681. * for addAttachment.
    682. -
    683. *
    684. -
    685. * @return array The attachments.
    686. -
    687. * @access public
    688. -
    689. */
    690. -
    691. function getAttachments() {
    692. -
    693. return $this->requestAttachments;
    694. -
    695. }
    696. -
    697.  
    698. -
    699. /**
    700. -
    701. * gets the HTTP body for the current response.
    702. -
    703. *
    704. -
    705. * @param string $soapmsg The SOAP payload
    706. -
    707. * @return string The HTTP body, which includes the SOAP payload
    708. -
    709. * @access private
    710. -
    711. */
    712. -
    713. function getHTTPBody($soapmsg) {
    714. -
    715. if (count($this->responseAttachments) > 0) {
    716. -
    717. $params['content_type'] = 'multipart/related; type="text/xml"';
    718. -
    719. $mimeMessage = new Mail_mimePart('', $params);
    720. -
    721. unset($params);
    722. -
    723.  
    724. -
    725. $params['content_type'] = 'text/xml';
    726. -
    727. $params['encoding'] = '8bit';
    728. -
    729. $params['charset'] = $this->soap_defencoding;
    730. -
    731. $mimeMessage->addSubpart($soapmsg, $params);
    732. -
    733. -
    734. foreach ($this->responseAttachments as $att) {
    735. -
    736. unset($params);
    737. -
    738.  
    739. -
    740. $params['content_type'] = $att['contenttype'];
    741. -
    742. $params['encoding'] = 'base64';
    743. -
    744. $params['disposition'] = 'attachment';
    745. -
    746. $params['dfilename'] = $att['filename'];
    747. -
    748. $params['cid'] = $att['cid'];
    749. -
    750.  
    751. -
    752. if ($att['data'] == '' && $att['filename'] <> '') {
    753. -
    754. if ($fd = fopen($att['filename'], 'rb')) {
    755. -
    756. $data = fread($fd, filesize($att['filename']));
    757. -
    758. fclose($fd);
    759. -
    760. } else {
    761. -
    762. $data = '';
    763. -
    764. }
    765. -
    766. $mimeMessage->addSubpart($data, $params);
    767. -
    768. } else {
    769. -
    770. $mimeMessage->addSubpart($att['data'], $params);
    771. -
    772. }
    773. -
    774. }
    775. -
    776.  
    777. -
    778. $output = $mimeMessage->encode();
    779. -
    780. $mimeHeaders = $output['headers'];
    781. -
    782. -
    783. foreach ($mimeHeaders as $k => $v) {
    784. -
    785. $this->debug("MIME header $k: $v");
    786. -
    787. if (strtolower($k) == 'content-type') {
    788. -
    789. // PHP header() seems to strip leading whitespace starting
    790. -
    791. // the second line, so force everything to one line
    792. -
    793. $this->mimeContentType = str_replace("\r\n", " ", $v);
    794. -
    795. }
    796. -
    797. }
    798. -
    799. -
    800. return $output['body'];
    801. -
    802. }
    803. -
    804.  
    805. -
    806. return parent::getHTTPBody($soapmsg);
    807. -
    808. }
    809. -
    810. -
    811. /**
    812. -
    813. * gets the HTTP content type for the current response.
    814. -
    815. *
    816. -
    817. * Note: getHTTPBody must be called before this.
    818. -
    819. *
    820. -
    821. * @return string the HTTP content type for the current response.
    822. -
    823. * @access private
    824. -
    825. */
    826. -
    827. function getHTTPContentType() {
    828. -
    829. if (count($this->responseAttachments) > 0) {
    830. -
    831. return $this->mimeContentType;
    832. -
    833. }
    834. -
    835. return parent::getHTTPContentType();
    836. -
    837. }
    838. -
    839. -
    840. /**
    841. -
    842. * gets the HTTP content type charset for the current response.
    843. -
    844. * returns false for non-text content types.
    845. -
    846. *
    847. -
    848. * Note: getHTTPBody must be called before this.
    849. -
    850. *
    851. -
    852. * @return string the HTTP content type charset for the current response.
    853. -
    854. * @access private
    855. -
    856. */
    857. -
    858. function getHTTPContentTypeCharset() {
    859. -
    860. if (count($this->responseAttachments) > 0) {
    861. -
    862. return false;
    863. -
    864. }
    865. -
    866. return parent::getHTTPContentTypeCharset();
    867. -
    868. }
    869. -
    870.  
    871. -
    872. /**
    873. -
    874. * processes SOAP message received from client
    875. -
    876. *
    877. -
    878. * @param array $headers The HTTP headers
    879. -
    880. * @param string $data unprocessed request data from client
    881. -
    882. * @return mixed value of the message, decoded into a PHP type
    883. -
    884. * @access private
    885. -
    886. */
    887. -
    888. function parseRequest($headers, $data) {
    889. -
    890. $this->debug('Entering parseRequest() for payload of length ' . strlen($data) . ' and type of ' . $headers['content-type']);
    891. -
    892. $this->requestAttachments = array();
    893. -
    894. if (strstr($headers['content-type'], 'multipart/related')) {
    895. -
    896. $this->debug('Decode multipart/related');
    897. -
    898. $input = '';
    899. -
    900. foreach ($headers as $k => $v) {
    901. -
    902. $input .= "$k: $v\r\n";
    903. -
    904. }
    905. -
    906. $params['input'] = $input . "\r\n" . $data;
    907. -
    908. $params['include_bodies'] = true;
    909. -
    910. $params['decode_bodies'] = true;
    911. -
    912. $params['decode_headers'] = true;
    913. -
    914. -
    915. $structure = Mail_mimeDecode::decode($params);
    916. -
    917.  
    918. -
    919. foreach ($structure->parts as $part) {
    920. -
    921. if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) {
    922. -
    923. $this->debug('Have root part of type ' . $part->headers['content-type']);
    924. -
    925. $return = parent::parseRequest($part->headers, $part->body);
    926. -
    927. } else {
    928. -
    929. $this->debug('Have an attachment of type ' . $part->headers['content-type']);
    930. -
    931. $info['data'] = $part->body;
    932. -
    933. $info['filename'] = isset($part->d_parameters['filename']) ? $part->d_parameters['filename'] : '';
    934. -
    935. $info['contenttype'] = $part->headers['content-type'];
    936. -
    937. $info['cid'] = $part->headers['content-id'];
    938. -
    939. $this->requestAttachments[] = $info;
    940. -
    941. }
    942. -
    943. }
    944. -
    945. -
    946. if (isset($return)) {
    947. -
    948. return $return;
    949. -
    950. }
    951. -
    952. -
    953. $this->setError('No root part found in multipart/related content');
    954. -
    955. return;
    956. -
    957. }
    958. -
    959. $this->debug('Not multipart/related');
    960. -
    961. return parent::parseRequest($headers, $data);
    962. -
    963. }
    964. -
    965. }
    966. -
    967.  
    968. -
    969. /*
    970. -
    971. * For backwards compatiblity
    972. -
    973. */
    974. -
    975. class nusoapservermime extends nusoap_server_mime {
    976. -
    977. }
    978. -
    979.  
    980. -
    981. ?>
    982. -
    -
    -

    - Documentation generated on Mon, 26 Apr 2010 16:17:09 -0400 by phpDocumentor 1.3.0RC3 -

    - - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/blank.html b/lib/nusoap/docs/docs/blank.html deleted file mode 100644 index d33898fc4..000000000 --- a/lib/nusoap/docs/docs/blank.html +++ /dev/null @@ -1,13 +0,0 @@ - - - phpDocumentor 1.3.0 Manual - - - - -

    phpDocumentor 1.3.0 Manual

    -Welcome to nusoap!
    -
    -This documentation was generated by phpDocumentor v1.3.0RC3
    - - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/classtrees_nusoap.html b/lib/nusoap/docs/docs/classtrees_nusoap.html deleted file mode 100644 index 34def4a56..000000000 --- a/lib/nusoap/docs/docs/classtrees_nusoap.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - -

    - -

    -

    Root class nusoap_base

    - - -

    Root class nusoap_wsdlcache

    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:16:48 -0400 by phpDocumentor 1.3.0RC3 -

    - - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/elementindex.html b/lib/nusoap/docs/docs/elementindex.html deleted file mode 100644 index 2b9eca66c..000000000 --- a/lib/nusoap/docs/docs/elementindex.html +++ /dev/null @@ -1,3290 +0,0 @@ - - - - - - - - - - - -

    Full index

    -

    Package indexes

    - -
    -
    - a - b - c - d - e - f - g - h - i - l - m - n - o - p - r - s - t - u - v - w - x - _ -
    - - -
    -
    a
    - -
    -
    -
    -
    - Variable - $attributes -
    -
    - -
    -
    - Variable - $attributes -
    -
    -
    soapval::$attributes in nusoap.php
    -
    The XML element attributes (array or false)
    -
    -
    - Variable - $authtype -
    -
    -
    wsdl::$authtype in nusoap.php
    -
    -
    - Variable - $authtype -
    -
    - -
    -
    - Variable - $authtype -
    -
    - -
    -
    - Method - addAttachment -
    -
    - -
    adds a MIME attachment to the current request.
    -
    -
    - Method - addAttachment -
    -
    - -
    adds a MIME attachment to the current response.
    -
    -
    - Method - addComplexType -
    -
    - -
    adds a complex type to the schema
    -
    -
    - Method - addComplexType -
    -
    - -
    adds an XML Schema complex type to the WSDL types
    -
    -
    - Method - addElement -
    -
    - -
    adds an element to the schema
    -
    -
    - Method - addElement -
    -
    -
    wsdl::addElement() in nusoap.php
    -
    adds an element to the WSDL types
    -
    -
    - Method - addOperation -
    -
    -
    wsdl::addOperation() in nusoap.php
    -
    register an operation with the server
    -
    -
    - Method - addSimpleType -
    -
    - -
    adds a simple type to the schema
    -
    -
    - Method - addSimpleType -
    -
    -
    wsdl::addSimpleType() in nusoap.php
    -
    adds an XML Schema simple type to the WSDL types
    -
    -
    - Method - add_to_map -
    -
    - -
    add a method to the dispatch map (this has been replaced by the register method)
    -
    -
    - Method - appendDebug -
    -
    - -
    adds debug data to the instance debug string without formatting
    -
    -
    - -
    -
    b
    - -
    -
    -
    -
    - Variable - $bindings -
    -
    -
    wsdl::$bindings in nusoap.php
    -
    -
    - Variable - $bindingType -
    -
    - -
    -
    - Variable - $body_position -
    -
    - -
    -
    - Method - buildPayload -
    -
    - -
    Writes the payload, including HTTP headers, to $this->outgoing_payload.
    -
    -
    - Method - buildVal -
    -
    - -
    builds response structures for compound values (arrays/structs) and scalars
    -
    -
    - -
    -
    c
    - -
    -
    -
    -
    - Variable - $cache_dir -
    -
    -
    nusoap_wsdlcache::$cache_dir in class.wsdlcache.php
    -
    -
    - Variable - $cache_lifetime -
    -
    -
    nusoap_wsdlcache::$cache_lifetime in class.wsdlcache.php
    -
    -
    - Variable - $certRequest -
    -
    - -
    -
    - Variable - $certRequest -
    -
    -
    wsdl::$certRequest in nusoap.php
    -
    -
    - Variable - $certRequest -
    -
    - -
    -
    - Variable - $ch -
    -
    - -
    -
    - Variable - $charencoding -
    -
    - -
    toggles automatic encoding of special characters as entities (should always be true, I think)
    -
    -
    - Variable - $ch_options -
    -
    - -
    -
    - Variable - $complexTypes -
    -
    - -
    -
    - Variable - $complexTypes -
    -
    -
    wsdl::$complexTypes in nusoap.php
    -
    -
    - Variable - $complexTypeStack -
    -
    - -
    -
    - Variable - $cookies -
    -
    - -
    -
    - Variable - $curl_options -
    -
    -
    wsdl::$curl_options in nusoap.php
    -
    -
    - Variable - $curl_options -
    -
    - -
    -
    - Variable - $currentBinding -
    -
    -
    wsdl::$currentBinding in nusoap.php
    -
    -
    - Variable - $currentComplexType -
    -
    - -
    -
    - Variable - $currentElement -
    -
    - -
    -
    - Variable - $currentMessage -
    -
    -
    wsdl::$currentMessage in nusoap.php
    -
    -
    - Variable - $currentOperation -
    -
    - -
    -
    - Variable - $currentPort -
    -
    -
    wsdl::$currentPort in nusoap.php
    -
    -
    - Variable - $currentPortType -
    -
    - -
    -
    - Variable - $currentSchema -
    -
    -
    wsdl::$currentSchema in nusoap.php
    -
    -
    - Variable - $currentSimpleType -
    -
    - -
    -
    - Method - call -
    -
    -
    nusoap_client::call() in nusoap.php
    -
    calls method, returns PHP native type
    -
    -
    - Method - character_data -
    -
    - -
    element content handler
    -
    -
    - Method - character_data -
    -
    - -
    element content handler
    -
    -
    - Method - checkCookies -
    -
    - -
    checks all Cookies and delete those which are expired
    -
    -
    - Method - checkWSDL -
    -
    - -
    check WSDL passed as an instance or pulled from an endpoint
    -
    -
    - Page - class.wsdlcache.php -
    -
    -
    class.wsdlcache.php in class.wsdlcache.php
    -
    -
    - Method - clearAttachments -
    -
    - -
    clears the MIME attachments for the current response.
    -
    -
    - Method - clearAttachments -
    -
    - -
    clears the MIME attachments for the current request.
    -
    -
    - Method - clearDebug -
    -
    - -
    clears the current debug data for this instance
    -
    -
    - Method - configureWSDL -
    -
    - -
    Sets up wsdl object.
    -
    -
    - Method - connect -
    -
    - -
    establish an HTTP connection
    -
    -
    - Method - contractQname -
    -
    - -
    contracts (changes namespace to prefix) a qualified name
    -
    -
    - Method - createFilename -
    -
    -
    nusoap_wsdlcache::createFilename() in class.wsdlcache.php
    -
    creates the filename used to cache a wsdl instance
    -
    -
    - Method - CreateTypeName -
    -
    - -
    gets a type name for an unnamed type
    -
    -
    - -
    -
    d
    - -
    -
    -
    -
    - Variable - $debugLevel -
    -
    - -
    the debug level for this instance
    -
    -
    - Variable - $debug_flag -
    -
    - -
    whether to append debug to response as XML comment
    -
    -
    - Variable - $debug_flag -
    -
    - -
    -
    - Variable - $debug_str -
    -
    - -
    Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
    -
    -
    - Variable - $debug_str -
    -
    -
    nusoap_wsdlcache::$debug_str in class.wsdlcache.php
    -
    -
    - Variable - $decode_utf8 -
    -
    - -
    toggles whether the parser decodes element content w/ utf8_decode()
    -
    -
    - Variable - $decode_utf8 -
    -
    - -
    -
    - Variable - $decode_utf8 -
    -
    - -
    -
    - Variable - $defaultNamespace -
    -
    - -
    -
    - Variable - $defaultRpcParams -
    -
    - -
    -
    - Variable - $default_namespace -
    -
    - -
    -
    - Variable - $depth -
    -
    -
    wsdl::$depth in nusoap.php
    -
    -
    - Variable - $depth -
    -
    - -
    -
    - Variable - $depth -
    -
    -
    nusoap_parser::$depth in nusoap.php
    -
    -
    - Variable - $depth_array -
    -
    - -
    -
    - Variable - $depth_array -
    -
    -
    wsdl::$depth_array in nusoap.php
    -
    -
    - Variable - $depth_array -
    -
    - -
    -
    - Variable - $digestRequest -
    -
    - -
    -
    - Variable - $digest_uri -
    -
    - -
    -
    - Variable - $document -
    -
    - -
    -
    - Variable - $document -
    -
    - -
    SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
    -
    -
    - Variable - $document -
    -
    - -
    -
    - Variable - $documentation -
    -
    -
    wsdl::$documentation in nusoap.php
    -
    -
    - Method - debug -
    -
    -
    nusoap_base::debug() in nusoap.php
    -
    adds debug data to the instance debug string with formatting
    -
    -
    - Method - debug -
    -
    -
    nusoap_wsdlcache::debug() in class.wsdlcache.php
    -
    adds debug data to the class level debug string
    -
    -
    - Method - decode -
    -
    -
    soapval::decode() in nusoap.php
    -
    decodes a soapval object into a PHP native type
    -
    -
    - Method - decodeChunked -
    -
    - -
    decode a string that is encoded w/ "chunked' transfer encoding as defined in RFC2068 19.4.6
    -
    -
    - Method - decodeSimple -
    -
    - -
    decodes simple types into PHP variables
    -
    -
    - Method - decodeUTF8 -
    -
    - -
    -
    - -
    -
    e
    - -
    -
    -
    -
    - Variable - $elements -
    -
    - -
    -
    - Variable - $elementStack -
    -
    - -
    -
    - Variable - $element_ns -
    -
    -
    soapval::$element_ns in nusoap.php
    -
    The XML element namespace (string or false)
    -
    -
    - Variable - $enclosingNamespaces -
    -
    - -
    -
    - Variable - $encoding -
    -
    - -
    -
    - Variable - $endpoint -
    -
    - -
    -
    - Variable - $endpoint -
    -
    -
    wsdl::$endpoint in nusoap.php
    -
    -
    - Variable - $endpointType -
    -
    - -
    -
    - Variable - $error_str -
    -
    - -
    Current error string (manipulated by getError/setError)
    -
    -
    - Variable - $externalWSDLURL -
    -
    - -
    URL for WSDL (if one)
    -
    -
    - Method - end_element -
    -
    -
    wsdl::end_element() in nusoap.php
    -
    end-element handler
    -
    -
    - Method - end_element -
    -
    - -
    end-element handler
    -
    -
    - Method - expandEntities -
    -
    - -
    expands entities, e.g. changes '<' to '&lt;'.
    -
    -
    - Method - expandQname -
    -
    - -
    expands (changes prefix to namespace) a qualified name
    -
    -
    - -
    -
    f
    - -
    -
    -
    -
    - Variable - $fault -
    -
    -
    nusoap_parser::$fault in nusoap.php
    -
    -
    - Variable - $fault -
    -
    -
    nusoap_client::$fault in nusoap.php
    -
    -
    - Variable - $fault -
    -
    -
    nusoap_server::$fault in nusoap.php
    -
    SOAP fault for response (or false)
    -
    -
    - Variable - $faultactor -
    -
    - -
    The fault actor
    -
    -
    - Variable - $faultcode -
    -
    - -
    The fault code (client|server)
    -
    -
    - Variable - $faultcode -
    -
    - -
    -
    - Variable - $faultdetail -
    -
    - -
    The fault detail, typically a string or array of string
    -
    -
    - Variable - $faultdetail -
    -
    - -
    -
    - Variable - $faultstring -
    -
    - -
    The fault string, a description of the fault
    -
    -
    - Variable - $faultstring -
    -
    - -
    -
    - Variable - $fault_code -
    -
    - -
    -
    - Variable - $fault_detail -
    -
    - -
    -
    - Variable - $fault_str -
    -
    - -
    -
    - Variable - $forceEndpoint -
    -
    - -
    -
    - Variable - $fplock -
    -
    -
    nusoap_wsdlcache::$fplock in class.wsdlcache.php
    -
    -
    - Method - fault -
    -
    - -
    Specify a fault to be returned to the client.
    -
    -
    - Method - fetchWSDL -
    -
    -
    wsdl::fetchWSDL() in nusoap.php
    -
    fetches the WSDL document and parses it
    -
    -
    - Method - formatDump -
    -
    - -
    formats a string to be inserted into an HTML stream
    -
    -
    - -
    -
    g
    - -
    -
    -
    -
    - Method - get -
    -
    -
    nusoap_wsdlcache::get() in class.wsdlcache.php
    -
    gets a wsdl instance from the cache
    -
    -
    - Method - getAttachments -
    -
    - -
    gets the MIME attachments from the current response.
    -
    -
    - Method - getAttachments -
    -
    - -
    gets the MIME attachments from the current request.
    -
    -
    - Method - getBindingData -
    -
    - -
    -
    - Method - getCookies -
    -
    - -
    gets all Cookies
    -
    -
    - Method - getCookiesForRequest -
    -
    - -
    sort out cookies for the current request
    -
    -
    - Method - getDebug -
    -
    - -
    gets the current debug data for this instance
    -
    -
    - Method - getDebugAsXMLComment -
    -
    - -
    gets the current debug data for this instance as an XML comment this may change the contents of the debug data
    -
    -
    - Method - getDebugLevel -
    -
    - -
    gets the debug level for this instance
    -
    -
    - Method - getDefaultRpcParams -
    -
    - -
    gets the default RPC parameter setting.
    -
    -
    - Method - getError -
    -
    - -
    returns error string if present
    -
    -
    - Method - getGlobalDebugLevel -
    -
    - -
    gets the global debug level, which applies to future instances
    -
    -
    - Method - getHeader -
    -
    - -
    get the SOAP response Header (parsed)
    -
    -
    - Method - getHeaders -
    -
    - -
    get the SOAP response headers (namespace resolution incomplete)
    -
    -
    - Method - getHeaders -
    -
    - -
    get the unparsed SOAP Header
    -
    -
    - Method - getHTTPBody -
    -
    - -
    gets the HTTP body for the current response.
    -
    -
    - Method - getHTTPBody -
    -
    - -
    gets the HTTP body for the current response.
    -
    -
    - Method - getHTTPBody -
    -
    - -
    gets the HTTP body for the current request.
    -
    -
    - Method - getHTTPBody -
    -
    - -
    gets the HTTP body for the current request.
    -
    -
    - Method - getHTTPContentType -
    -
    - -
    gets the HTTP content type for the current response.
    -
    -
    - Method - getHTTPContentType -
    -
    - -
    gets the HTTP content type for the current request.
    -
    -
    - Method - getHTTPContentType -
    -
    - -
    gets the HTTP content type for the current response.
    -
    -
    - Method - getHTTPContentType -
    -
    - -
    gets the HTTP content type for the current request.
    -
    -
    - Method - getHTTPContentTypeCharset -
    -
    - -
    gets the HTTP content type charset for the current request.
    -
    -
    - Method - getHTTPContentTypeCharset -
    -
    - -
    gets the HTTP content type charset for the current response.
    -
    -
    - Method - getHTTPContentTypeCharset -
    -
    - -
    gets the HTTP content type charset for the current request.
    -
    -
    - Method - getHTTPContentTypeCharset -
    -
    - -
    gets the HTTP content type charset for the current response.
    -
    -
    - Method - getLocalPart -
    -
    - -
    returns the local part of a prefixed string returns the original string, if not prefixed
    -
    -
    - Method - getmicrotime -
    -
    - -
    returns the time in ODBC canonical form with microseconds
    -
    -
    - Method - getNamespaceFromPrefix -
    -
    - -
    pass it a prefix, it returns a namespace
    -
    -
    - Method - getOperationData -
    -
    - -
    returns an associative array of data necessary for calling an operation
    -
    -
    - Method - getOperationData -
    -
    - -
    get available data pertaining to an operation
    -
    -
    - Method - getOperationDataForSoapAction -
    -
    - -
    returns an associative array of data necessary for calling an operation
    -
    -
    - Method - getOperations -
    -
    -
    wsdl::getOperations() in nusoap.php
    -
    returns an assoc array of operation names => operation data
    -
    -
    - Method - getPHPType -
    -
    - -
    get the PHP type of a user defined type in the schema
    -
    -
    - Method - getPrefix -
    -
    - -
    returns the prefix part of a prefixed string returns false, if not prefixed
    -
    -
    - Method - getPrefixFromNamespace -
    -
    - -
    returns the prefix for a given namespace (or prefix) or false if no prefixes registered for the given namespace
    -
    -
    - Method - getProxy -
    -
    - -
    dynamically creates an instance of a proxy class, allowing user to directly call methods from wsdl
    -
    -
    - Method - getProxyClassCode -
    -
    - -
    dynamically creates proxy class code
    -
    -
    - Method - getResponse -
    -
    - -
    gets the SOAP response via HTTP[S]
    -
    -
    - Method - getTypeDef -
    -
    - -
    returns an associative array of information about a given type returns false if no type exists by the given name
    -
    -
    - Method - getTypeDef -
    -
    -
    wsdl::getTypeDef() in nusoap.php
    -
    returns an array of information about a given type returns false if no type exists by the given name
    -
    -
    - Method - get_response -
    -
    - -
    get the parsed message (SOAP Body)
    -
    -
    - Method - get_soapbody -
    -
    - -
    get the parsed SOAP Body (NULL if there was none)
    -
    -
    - Method - get_soapheader -
    -
    - -
    get the parsed SOAP Header (NULL if there was none)
    -
    -
    - -
    -
    h
    - -
    -
    -
    -
    - Variable - $headers -
    -
    - -
    HTTP headers of request
    -
    -
    - Variable - $host -
    -
    - -
    -
    - Variable - $http_encoding -
    -
    - -
    -
    - -
    -
    i
    - -
    -
    -
    -
    - Variable - $ids -
    -
    -
    nusoap_parser::$ids in nusoap.php
    -
    -
    - Variable - $import -
    -
    -
    wsdl::$import in nusoap.php
    -
    -
    - Variable - $imports -
    -
    - -
    -
    - Variable - $incoming_cookies -
    -
    - -
    -
    - Variable - $incoming_headers -
    -
    - -
    -
    - Variable - $incoming_payload -
    -
    - -
    -
    - Method - invoke_method -
    -
    - -
    invokes a PHP function for the requested SOAP method
    -
    -
    - Method - io_method -
    -
    - -
    gets the I/O method to use
    -
    -
    - Method - isArraySimpleOrStruct -
    -
    - -
    detect if array is a simple array or a struct (associative array)
    -
    -
    - Function - iso8601_to_timestamp -
    -
    - -
    convert ISO 8601 compliant date string to unix timestamp
    -
    -
    - Method - isSkippableCurlHeader -
    -
    - -
    Test if the given string starts with a header that is to be skipped.
    -
    -
    - -
    -
    l
    - -
    -
    -
    -
    - Method - loadWSDL -
    -
    - -
    instantiate wsdl object and parse wsdl file
    -
    -
    - -
    -
    m
    - -
    -
    -
    -
    - Variable - $message -
    -
    - -
    -
    - Variable - $message -
    -
    -
    wsdl::$message in nusoap.php
    -
    -
    - Variable - $message -
    -
    - -
    -
    - Variable - $messages -
    -
    -
    wsdl::$messages in nusoap.php
    -
    -
    - Variable - $method -
    -
    - -
    -
    - Variable - $methodname -
    -
    - -
    name of method requested
    -
    -
    - Variable - $methodparams -
    -
    - -
    method parameters from request
    -
    -
    - Variable - $methodreturn -
    -
    - -
    method return value to place in response
    -
    -
    - Variable - $methodreturnisliteralxml -
    -
    - -
    whether $methodreturn is a string of literal XML
    -
    -
    - Variable - $methodURI -
    -
    - -
    requested method namespace URI
    -
    -
    - Variable - $mimeContentType -
    -
    - -
    -
    - Variable - $mimeContentType -
    -
    - -
    -
    - Variable - $multirefs -
    -
    - -
    -
    - -
    -
    n
    - -
    -
    -
    -
    - Variable - $name -
    -
    -
    soapval::$name in nusoap.php
    -
    The XML element name
    -
    -
    - Variable - $namespaces -
    -
    - -
    -
    - Variable - $namespaces -
    -
    - -
    namespaces in an array of prefix => uri
    -
    -
    - Page - nusoapmime.php -
    -
    -
    nusoapmime.php in nusoapmime.php
    -
    -
    - Class - nusoapservermime -
    -
    -
    nusoapservermime in nusoapmime.php
    -
    nusoap_server_mime server supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
    -
    -
    - Method - nusoap_base -
    -
    - -
    constructor
    -
    -
    - Class - nusoap_base -
    -
    -
    nusoap_base in nusoap.php
    -
    nusoap_base
    -
    -
    - Class - nusoap_client -
    -
    -
    nusoap_client in nusoap.php
    -
    [nu]soapclient higher level class for easy usage.
    -
    -
    - Method - nusoap_client -
    -
    - -
    constructor
    -
    -
    - Class - nusoap_client_mime -
    -
    -
    nusoap_client_mime in nusoapmime.php
    -
    nusoap_client_mime client supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
    -
    -
    - Class - nusoap_fault -
    -
    -
    nusoap_fault in nusoap.php
    -
    Contains information for a SOAP fault.
    -
    -
    - Method - nusoap_fault -
    -
    - -
    constructor
    -
    -
    - Class - nusoap_parser -
    -
    -
    nusoap_parser in nusoap.php
    -
    nusoap_parser class parses SOAP XML messages into native PHP values
    -
    -
    - Method - nusoap_parser -
    -
    - -
    constructor that actually does the parsing
    -
    -
    - Page - nusoap.php -
    -
    -
    nusoap.php in nusoap.php
    -
    -
    - Method - nusoap_server -
    -
    - -
    constructor the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
    -
    -
    - Class - nusoap_server -
    -
    -
    nusoap_server in nusoap.php
    -
    nusoap_server allows the user to create a SOAP server that is capable of receiving messages and returning responses
    -
    -
    - Class - nusoap_server_mime -
    -
    -
    nusoap_server_mime in nusoapmime.php
    -
    nusoap_server_mime server supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
    -
    -
    - Class - nusoap_wsdlcache -
    -
    -
    nusoap_wsdlcache in class.wsdlcache.php
    -
    caches instances of the wsdl class
    -
    -
    - Method - nusoap_wsdlcache -
    -
    - -
    constructor
    -
    -
    - Class - nusoap_xmlschema -
    -
    -
    nusoap_xmlschema in nusoap.php
    -
    parses an XML Schema, allows access to it's data, other utility methods.
    -
    -
    - Method - nusoap_xmlschema -
    -
    - -
    constructor
    -
    -
    - -
    -
    o
    - -
    -
    -
    -
    - Variable - $opData -
    -
    -
    wsdl::$opData in nusoap.php
    -
    -
    - Variable - $operations -
    -
    - -
    assoc array of operations => opData; operations are added by the register()
    -
    -
    - Variable - $operations -
    -
    - -
    -
    - Variable - $outgoing_headers -
    -
    - -
    -
    - Variable - $outgoing_headers -
    -
    - -
    HTTP headers of response
    -
    -
    - Variable - $outgoing_payload -
    -
    - -
    -
    - Method - obtainMutex -
    -
    -
    nusoap_wsdlcache::obtainMutex() in class.wsdlcache.php
    -
    obtains the local mutex
    -
    -
    - -
    -
    p
    - -
    -
    -
    -
    - Variable - $parent -
    -
    - -
    -
    - Variable - $parser -
    -
    -
    wsdl::$parser in nusoap.php
    -
    -
    - Variable - $parser -
    -
    - -
    -
    - Variable - $password -
    -
    -
    wsdl::$password in nusoap.php
    -
    -
    - Variable - $password -
    -
    - -
    -
    - Variable - $password -
    -
    - -
    -
    - Variable - $path -
    -
    - -
    -
    - Variable - $persistentConnection -
    -
    - -
    -
    - Variable - $persistentConnection -
    -
    - -
    -
    - Variable - $port -
    -
    - -
    -
    - Variable - $portName -
    -
    - -
    -
    - Variable - $ports -
    -
    -
    wsdl::$ports in nusoap.php
    -
    -
    - Variable - $portTypes -
    -
    -
    wsdl::$portTypes in nusoap.php
    -
    -
    - Variable - $position -
    -
    - -
    -
    - Variable - $position -
    -
    - -
    -
    - Variable - $position -
    -
    -
    wsdl::$position in nusoap.php
    -
    -
    - Variable - $protocol_version -
    -
    - -
    -
    - Variable - $proxy -
    -
    - -
    -
    - Variable - $proxyhost -
    -
    -
    wsdl::$proxyhost in nusoap.php
    -
    -
    - Variable - $proxyhost -
    -
    - -
    -
    - Variable - $proxypassword -
    -
    - -
    -
    - Variable - $proxypassword -
    -
    -
    wsdl::$proxypassword in nusoap.php
    -
    -
    - Variable - $proxyport -
    -
    -
    wsdl::$proxyport in nusoap.php
    -
    -
    - Variable - $proxyport -
    -
    - -
    -
    - Variable - $proxyusername -
    -
    - -
    -
    - Variable - $proxyusername -
    -
    -
    wsdl::$proxyusername in nusoap.php
    -
    -
    - Method - parametersMatchWrapped -
    -
    - -
    determine whether a set of parameters are unwrapped when they are expect to be wrapped, Microsoft-style.
    -
    -
    - Method - parseCookie -
    -
    - -
    parse an incoming Cookie into it's parts
    -
    -
    - Method - parseFile -
    -
    - -
    parse an XML file
    -
    -
    - Method - parseRequest -
    -
    - -
    processes SOAP message received from client
    -
    -
    - Method - parseRequest -
    -
    - -
    processes SOAP message received from client
    -
    -
    - Method - parseResponse -
    -
    - -
    processes SOAP message returned from server
    -
    -
    - Method - parseResponse -
    -
    - -
    processes SOAP message returned from server
    -
    -
    - Method - parseString -
    -
    - -
    parse an XML string
    -
    -
    - Method - parseWSDL -
    -
    -
    wsdl::parseWSDL() in nusoap.php
    -
    parses the wsdl document
    -
    -
    - Method - parse_http_headers -
    -
    - -
    parses HTTP request headers.
    -
    -
    - Method - parse_request -
    -
    - -
    parses a request
    -
    -
    - Method - put -
    -
    -
    nusoap_wsdlcache::put() in class.wsdlcache.php
    -
    adds a wsdl instance to the cache
    -
    -
    - -
    -
    r
    - -
    -
    -
    -
    - Variable - $request -
    -
    - -
    HTTP request
    -
    -
    - Variable - $request -
    -
    - -
    -
    - Variable - $requestAttachments -
    -
    - -
    -
    - Variable - $requestAttachments -
    -
    - -
    -
    - Variable - $requestHeader -
    -
    - -
    SOAP Headers from request (parsed)
    -
    -
    - Variable - $requestHeaders -
    -
    - -
    SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
    -
    -
    - Variable - $requestHeaders -
    -
    - -
    -
    - Variable - $requestSOAP -
    -
    - -
    SOAP payload for request (text)
    -
    -
    - Variable - $request_method -
    -
    - -
    -
    - Variable - $response -
    -
    - -
    -
    - Variable - $response -
    -
    - -
    HTTP response
    -
    -
    - Variable - $responseAttachments -
    -
    - -
    -
    - Variable - $responseAttachments -
    -
    - -
    -
    - Variable - $responseData -
    -
    - -
    -
    - Variable - $responseHeader -
    -
    - -
    -
    - Variable - $responseHeaders -
    -
    - -
    -
    - Variable - $responseHeaders -
    -
    - -
    SOAP headers for response (text or array of soapval or associative array)
    -
    -
    - Variable - $responseHeaders -
    -
    - -
    -
    - Variable - $responseSOAP -
    -
    - -
    SOAP payload for response (text)
    -
    -
    - Variable - $response_status_line -
    -
    - -
    -
    - Variable - $response_timeout -
    -
    - -
    -
    - Variable - $response_timeout -
    -
    - -
    -
    - Variable - $result -
    -
    - -
    text indication of result (for debugging)
    -
    -
    - Variable - $revision -
    -
    - -
    CVS revision for HTTP headers.
    -
    -
    - Variable - $root_header -
    -
    - -
    -
    - Variable - $root_struct -
    -
    - -
    -
    - Variable - $root_struct_name -
    -
    - -
    -
    - Variable - $root_struct_namespace -
    -
    - -
    -
    - Method - register -
    -
    - -
    register a service function with the server
    -
    -
    - Method - releaseMutex -
    -
    -
    nusoap_wsdlcache::releaseMutex() in class.wsdlcache.php
    -
    releases the local mutex
    -
    -
    - Method - remove -
    -
    -
    nusoap_wsdlcache::remove() in class.wsdlcache.php
    -
    removes a wsdl instance from the cache
    -
    -
    - -
    -
    s
    - -
    -
    -
    -
    - Variable - $schema -
    -
    - -
    -
    - Variable - $schemaInfo -
    -
    - -
    -
    - Variable - $schemas -
    -
    -
    wsdl::$schemas in nusoap.php
    -
    -
    - Variable - $schemaTargetNamespace -
    -
    - -
    -
    - Variable - $scheme -
    -
    - -
    -
    - Variable - $simpleTypes -
    -
    - -
    -
    - Variable - $simpleTypeStack -
    -
    - -
    -
    - Variable - $SOAPAction -
    -
    - -
    SOAP Action from request
    -
    -
    - Variable - $soapheader -
    -
    - -
    -
    - Variable - $soapresponse -
    -
    - -
    -
    - Variable - $soap_defencoding -
    -
    - -
    charset encoding for outgoing messages
    -
    -
    - Variable - $status -
    -
    -
    wsdl::$status in nusoap.php
    -
    -
    - Variable - $status -
    -
    - -
    -
    - Method - schemaCharacterData -
    -
    - -
    element content handler
    -
    -
    - Method - schemaEndElement -
    -
    - -
    end-element handler
    -
    -
    - Method - schemaStartElement -
    -
    - -
    start-element handler
    -
    -
    - Method - send -
    -
    -
    nusoap_client::send() in nusoap.php
    -
    send the SOAP message
    -
    -
    - Method - send -
    -
    - -
    sends the SOAP request and gets the SOAP response via HTTP[S]
    -
    -
    - Method - sendHTTPS -
    -
    - -
    sends the SOAP request and gets the SOAP response via HTTPS using CURL
    -
    -
    - Method - sendRequest -
    -
    - -
    sends the SOAP request via HTTP[S]
    -
    -
    - Method - send_response -
    -
    - -
    sends an HTTP response
    -
    -
    - Method - serialize -
    -
    -
    soapval::serialize() in nusoap.php
    -
    return serialized value
    -
    -
    - Method - serialize -
    -
    - -
    serialize a fault
    -
    -
    - Method - serialize -
    -
    -
    wsdl::serialize() in nusoap.php
    -
    serialize the parsed wsdl
    -
    -
    - Method - serializeComplexTypeAttributes -
    -
    - -
    serializes the attributes for a complexType
    -
    -
    - Method - serializeComplexTypeElements -
    -
    - -
    serializes the elements for a complexType
    -
    -
    - Method - serializeEnvelope -
    -
    - -
    serializes a message
    -
    -
    - Method - serializeParameters -
    -
    - -
    serialize a PHP value according to a WSDL message definition
    -
    -
    - Method - serializeRPCParameters -
    -
    - -
    serialize PHP values according to a WSDL message definition contrary to the method name, this is not limited to RPC
    -
    -
    - Method - serializeSchema -
    -
    - -
    serialize the schema
    -
    -
    - Method - serializeType -
    -
    -
    wsdl::serializeType() in nusoap.php
    -
    serializes a PHP value according a given type definition
    -
    -
    - Method - serializeTypeDef -
    -
    - -
    returns a sample serialization of a given type, or false if no type by the given name
    -
    -
    - Method - serialize_return -
    -
    - -
    serializes the return value from a PHP function into a full SOAP Envelope
    -
    -
    - Method - serialize_val -
    -
    - -
    serializes PHP values in accordance w/ section 5. Type information is not serialized if $use == 'literal'.
    -
    -
    - Method - service -
    -
    - -
    processes request and returns response
    -
    -
    - Method - setContentType -
    -
    - -
    sets the content-type for the SOAP message to be sent
    -
    -
    - Method - setCookie -
    -
    - -
    adds a new Cookie into $this->cookies array
    -
    -
    - Method - setCredentials -
    -
    - -
    if authenticating, set user credentials here
    -
    -
    - Method - setCredentials -
    -
    - -
    if authenticating, set user credentials here
    -
    -
    - Method - setCredentials -
    -
    - -
    if authenticating, set user credentials here
    -
    -
    - Method - setCurlOption -
    -
    - -
    sets a cURL option
    -
    -
    - Method - setCurlOption -
    -
    - -
    sets user-specified cURL options
    -
    -
    - Method - setDebugLevel -
    -
    - -
    sets the debug level for this instance
    -
    -
    - Method - setDefaultRpcParams -
    -
    - -
    sets the default RPC parameter setting.
    -
    -
    - Method - setEncoding -
    -
    - -
    use http encoding
    -
    -
    - Method - setEndpoint -
    -
    - -
    sets the SOAP endpoint, which can override WSDL
    -
    -
    - Method - setError -
    -
    - -
    sets error string
    -
    -
    - Method - setGlobalDebugLevel -
    -
    - -
    sets the global debug level, which applies to future instances
    -
    -
    - Method - setHeader -
    -
    - -
    sets an HTTP header
    -
    -
    - Method - setHeaders -
    -
    - -
    set the SOAP headers
    -
    -
    - Method - setHTTPEncoding -
    -
    - -
    use HTTP encoding
    -
    -
    - Method - setHTTPProxy -
    -
    - -
    set proxy info here
    -
    -
    - Method - setProxy -
    -
    - -
    set proxy info here
    -
    -
    - Method - setSOAPAction -
    -
    - -
    set the soapaction value
    -
    -
    - Method - setURL -
    -
    - -
    sets the URL to which to connect
    -
    -
    - Method - setUseCURL -
    -
    - -
    Set whether to try to use cURL connections if possible
    -
    -
    - Class - soapclient -
    -
    -
    soapclient in nusoap.php
    -
    For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
    -
    -
    - Class - soapclientmime -
    -
    -
    soapclientmime in nusoapmime.php
    -
    nusoap_client_mime client supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
    -
    -
    - Method - soapval -
    -
    -
    soapval::soapval() in nusoap.php
    -
    constructor
    -
    -
    - Class - soapval -
    -
    -
    soapval in nusoap.php
    -
    For creating serializable abstractions of native PHP types. This class
    -
    -
    - Class - soap_fault -
    -
    -
    soap_fault in nusoap.php
    -
    Backward compatibility
    -
    -
    - Class - soap_parser -
    -
    -
    soap_parser in nusoap.php
    -
    Backward compatibility
    -
    -
    - Class - soap_server -
    -
    -
    soap_server in nusoap.php
    -
    Backward compatibility
    -
    -
    - Method - soap_transport_http -
    -
    - -
    constructor
    -
    -
    - Class - soap_transport_http -
    -
    -
    soap_transport_http in nusoap.php
    -
    transport class for sending/receiving data via HTTP and HTTPS NOTE: PHP must be compiled with the CURL extension for HTTPS support
    -
    -
    - Method - start_element -
    -
    -
    wsdl::start_element() in nusoap.php
    -
    start-element handler
    -
    -
    - Method - start_element -
    -
    - -
    start-element handler
    -
    -
    - -
    -
    t
    - -
    -
    -
    -
    - Variable - $timeout -
    -
    -
    wsdl::$timeout in nusoap.php
    -
    -
    - Variable - $timeout -
    -
    - -
    -
    - Variable - $title -
    -
    -
    nusoap_base::$title in nusoap.php
    -
    Identification for HTTP headers.
    -
    -
    - Variable - $type -
    -
    -
    soapval::$type in nusoap.php
    -
    The XML type name (string or false)
    -
    -
    - Variable - $typemap -
    -
    -
    nusoap_base::$typemap in nusoap.php
    -
    XML Schema types in an array of uri => (array of xml type => php type) is this legacy yet? no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
    -
    -
    - Variable - $type_ns -
    -
    -
    soapval::$type_ns in nusoap.php
    -
    The XML type namespace (string or false)
    -
    -
    - Function - timestamp_to_iso8601 -
    -
    - -
    convert unix timestamp to ISO 8601 compliant date string
    -
    -
    - Method - typeToForm -
    -
    - -
    returns HTML form elements that allow a user to enter values for creating an instance of the given type.
    -
    -
    - -
    -
    u
    - -
    -
    -
    -
    - Variable - $uri -
    -
    - -
    -
    - Variable - $url -
    -
    - -
    -
    - Variable - $usedNamespaces -
    -
    - -
    namespaces used in the current context, e.g. during serialization
    -
    -
    - Variable - $username -
    -
    - -
    -
    - Variable - $username -
    -
    -
    wsdl::$username in nusoap.php
    -
    -
    - Variable - $username -
    -
    - -
    -
    - Variable - $useSOAPAction -
    -
    - -
    -
    - Variable - $use_curl -
    -
    - -
    -
    - Variable - $use_curl -
    -
    -
    wsdl::$use_curl in nusoap.php
    -
    -
    - Variable - $use_curl -
    -
    - -
    -
    - Method - unsetHeader -
    -
    - -
    unsets an HTTP header
    -
    -
    - Method - UpdateCookies -
    -
    - -
    updates the current cookies with a new set
    -
    -
    - Method - useHTTPPersistentConnection -
    -
    - -
    use HTTP persistent connections if possible
    -
    -
    - Method - usePersistentConnection -
    -
    - -
    specifies that an HTTP persistent connection should be used
    -
    -
    - Function - usleepWindows -
    -
    -
    usleepWindows() in nusoap.php
    -
    sleeps some number of microseconds
    -
    -
    - -
    -
    v
    - -
    -
    -
    -
    - Variable - $value -
    -
    -
    soapval::$value in nusoap.php
    -
    The PHP value
    -
    -
    - Variable - $version -
    -
    -
    nusoap_base::$version in nusoap.php
    -
    Version for HTTP headers.
    -
    -
    - Method - varDump -
    -
    - -
    Returns a string with the output of var_dump
    -
    -
    - Method - verify_method -
    -
    - -
    takes the value that was created by parsing the request and compares to the method's signature, if available.
    -
    -
    - -
    -
    w
    - -
    -
    -
    -
    - Variable - $wsdl -
    -
    -
    wsdl::$wsdl in nusoap.php
    -
    -
    - Variable - $wsdl -
    -
    -
    nusoap_server::$wsdl in nusoap.php
    -
    wsdl instance (if one)
    -
    -
    - Method - webDescription -
    -
    - -
    prints html description of services
    -
    -
    - Method - wsdl -
    -
    -
    wsdl::wsdl() in nusoap.php
    -
    constructor
    -
    -
    - Class - wsdl -
    -
    -
    wsdl in nusoap.php
    -
    parses a WSDL file, allows access to it's data, other utility methods.
    -
    -
    - Class - wsdlcache -
    -
    -
    wsdlcache in class.wsdlcache.php
    -
    For backward compatibility
    -
    -
    - -
    -
    x
    - -
    -
    -
    -
    - Variable - $xml -
    -
    -
    nusoap_parser::$xml in nusoap.php
    -
    -
    - Variable - $xml -
    -
    - -
    -
    - Variable - $xmlEntities -
    -
    - -
    XML entities to convert
    -
    -
    - Variable - $XMLSchemaVersion -
    -
    - -
    set schema version
    -
    -
    - Variable - $xml_encoding -
    -
    - -
    character set encoding of incoming (request) messages
    -
    -
    - Variable - $xml_encoding -
    -
    - -
    -
    - Variable - $xml_encoding -
    -
    - -
    -
    - Method - xdebug -
    -
    - -
    adds debug data to the clas level debug string
    -
    -
    - Class - XMLSchema -
    -
    -
    XMLSchema in nusoap.php
    -
    Backward compatibility
    -
    -
    - -
    -
    _
    - -
    -
    -
    -
    - Method - _getProxyClassCode -
    -
    - -
    dynamically creates proxy class code
    -
    -
    - Method - __toString -
    -
    - -
    represents the object as a string
    -
    -
    - -
    - a - b - c - d - e - f - g - h - i - l - m - n - o - p - r - s - t - u - v - w - x - _ -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/elementindex_nusoap.html b/lib/nusoap/docs/docs/elementindex_nusoap.html deleted file mode 100644 index 23c86d492..000000000 --- a/lib/nusoap/docs/docs/elementindex_nusoap.html +++ /dev/null @@ -1,3287 +0,0 @@ - - - - - - - - - - - -

    [nusoap] element index

    -All elements -
    -
    - a - b - c - d - e - f - g - h - i - l - m - n - o - p - r - s - t - u - v - w - x - _ -
    - - -
    -
    _
    - -
    -
    -
    -
    - Method - _getProxyClassCode -
    -
    - -
    dynamically creates proxy class code
    -
    -
    - Method - __toString -
    -
    - -
    represents the object as a string
    -
    -
    - -
    -
    a
    - -
    -
    -
    -
    - Variable - $attributes -
    -
    - -
    -
    - Variable - $attributes -
    -
    -
    soapval::$attributes in nusoap.php
    -
    The XML element attributes (array or false)
    -
    -
    - Variable - $authtype -
    -
    -
    wsdl::$authtype in nusoap.php
    -
    -
    - Variable - $authtype -
    -
    - -
    -
    - Variable - $authtype -
    -
    - -
    -
    - Method - addAttachment -
    -
    - -
    adds a MIME attachment to the current request.
    -
    -
    - Method - addAttachment -
    -
    - -
    adds a MIME attachment to the current response.
    -
    -
    - Method - addComplexType -
    -
    - -
    adds a complex type to the schema
    -
    -
    - Method - addComplexType -
    -
    - -
    adds an XML Schema complex type to the WSDL types
    -
    -
    - Method - addElement -
    -
    - -
    adds an element to the schema
    -
    -
    - Method - addElement -
    -
    -
    wsdl::addElement() in nusoap.php
    -
    adds an element to the WSDL types
    -
    -
    - Method - addOperation -
    -
    -
    wsdl::addOperation() in nusoap.php
    -
    register an operation with the server
    -
    -
    - Method - addSimpleType -
    -
    - -
    adds a simple type to the schema
    -
    -
    - Method - addSimpleType -
    -
    -
    wsdl::addSimpleType() in nusoap.php
    -
    adds an XML Schema simple type to the WSDL types
    -
    -
    - Method - add_to_map -
    -
    - -
    add a method to the dispatch map (this has been replaced by the register method)
    -
    -
    - Method - appendDebug -
    -
    - -
    adds debug data to the instance debug string without formatting
    -
    -
    - -
    -
    b
    - -
    -
    -
    -
    - Variable - $bindings -
    -
    -
    wsdl::$bindings in nusoap.php
    -
    -
    - Variable - $bindingType -
    -
    - -
    -
    - Variable - $body_position -
    -
    - -
    -
    - Method - buildPayload -
    -
    - -
    Writes the payload, including HTTP headers, to $this->outgoing_payload.
    -
    -
    - Method - buildVal -
    -
    - -
    builds response structures for compound values (arrays/structs) and scalars
    -
    -
    - -
    -
    c
    - -
    -
    -
    -
    - Variable - $cache_dir -
    -
    -
    nusoap_wsdlcache::$cache_dir in class.wsdlcache.php
    -
    -
    - Variable - $cache_lifetime -
    -
    -
    nusoap_wsdlcache::$cache_lifetime in class.wsdlcache.php
    -
    -
    - Variable - $certRequest -
    -
    - -
    -
    - Variable - $certRequest -
    -
    -
    wsdl::$certRequest in nusoap.php
    -
    -
    - Variable - $certRequest -
    -
    - -
    -
    - Variable - $ch -
    -
    - -
    -
    - Variable - $charencoding -
    -
    - -
    toggles automatic encoding of special characters as entities (should always be true, I think)
    -
    -
    - Variable - $ch_options -
    -
    - -
    -
    - Variable - $complexTypes -
    -
    - -
    -
    - Variable - $complexTypes -
    -
    -
    wsdl::$complexTypes in nusoap.php
    -
    -
    - Variable - $complexTypeStack -
    -
    - -
    -
    - Variable - $cookies -
    -
    - -
    -
    - Variable - $curl_options -
    -
    -
    wsdl::$curl_options in nusoap.php
    -
    -
    - Variable - $curl_options -
    -
    - -
    -
    - Variable - $currentBinding -
    -
    -
    wsdl::$currentBinding in nusoap.php
    -
    -
    - Variable - $currentComplexType -
    -
    - -
    -
    - Variable - $currentElement -
    -
    - -
    -
    - Variable - $currentMessage -
    -
    -
    wsdl::$currentMessage in nusoap.php
    -
    -
    - Variable - $currentOperation -
    -
    - -
    -
    - Variable - $currentPort -
    -
    -
    wsdl::$currentPort in nusoap.php
    -
    -
    - Variable - $currentPortType -
    -
    - -
    -
    - Variable - $currentSchema -
    -
    -
    wsdl::$currentSchema in nusoap.php
    -
    -
    - Variable - $currentSimpleType -
    -
    - -
    -
    - Method - call -
    -
    -
    nusoap_client::call() in nusoap.php
    -
    calls method, returns PHP native type
    -
    -
    - Method - character_data -
    -
    - -
    element content handler
    -
    -
    - Method - character_data -
    -
    - -
    element content handler
    -
    -
    - Method - checkCookies -
    -
    - -
    checks all Cookies and delete those which are expired
    -
    -
    - Method - checkWSDL -
    -
    - -
    check WSDL passed as an instance or pulled from an endpoint
    -
    -
    - Page - class.wsdlcache.php -
    -
    -
    class.wsdlcache.php in class.wsdlcache.php
    -
    -
    - Method - clearAttachments -
    -
    - -
    clears the MIME attachments for the current response.
    -
    -
    - Method - clearAttachments -
    -
    - -
    clears the MIME attachments for the current request.
    -
    -
    - Method - clearDebug -
    -
    - -
    clears the current debug data for this instance
    -
    -
    - Method - configureWSDL -
    -
    - -
    Sets up wsdl object.
    -
    -
    - Method - connect -
    -
    - -
    establish an HTTP connection
    -
    -
    - Method - contractQname -
    -
    - -
    contracts (changes namespace to prefix) a qualified name
    -
    -
    - Method - createFilename -
    -
    -
    nusoap_wsdlcache::createFilename() in class.wsdlcache.php
    -
    creates the filename used to cache a wsdl instance
    -
    -
    - Method - CreateTypeName -
    -
    - -
    gets a type name for an unnamed type
    -
    -
    - -
    -
    d
    - -
    -
    -
    -
    - Variable - $debugLevel -
    -
    - -
    the debug level for this instance
    -
    -
    - Variable - $debug_flag -
    -
    - -
    whether to append debug to response as XML comment
    -
    -
    - Variable - $debug_flag -
    -
    - -
    -
    - Variable - $debug_str -
    -
    - -
    Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
    -
    -
    - Variable - $debug_str -
    -
    -
    nusoap_wsdlcache::$debug_str in class.wsdlcache.php
    -
    -
    - Variable - $decode_utf8 -
    -
    - -
    toggles whether the parser decodes element content w/ utf8_decode()
    -
    -
    - Variable - $decode_utf8 -
    -
    - -
    -
    - Variable - $decode_utf8 -
    -
    - -
    -
    - Variable - $defaultNamespace -
    -
    - -
    -
    - Variable - $defaultRpcParams -
    -
    - -
    -
    - Variable - $default_namespace -
    -
    - -
    -
    - Variable - $depth -
    -
    -
    wsdl::$depth in nusoap.php
    -
    -
    - Variable - $depth -
    -
    - -
    -
    - Variable - $depth -
    -
    -
    nusoap_parser::$depth in nusoap.php
    -
    -
    - Variable - $depth_array -
    -
    - -
    -
    - Variable - $depth_array -
    -
    -
    wsdl::$depth_array in nusoap.php
    -
    -
    - Variable - $depth_array -
    -
    - -
    -
    - Variable - $digestRequest -
    -
    - -
    -
    - Variable - $digest_uri -
    -
    - -
    -
    - Variable - $document -
    -
    - -
    -
    - Variable - $document -
    -
    - -
    SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
    -
    -
    - Variable - $document -
    -
    - -
    -
    - Variable - $documentation -
    -
    -
    wsdl::$documentation in nusoap.php
    -
    -
    - Method - debug -
    -
    -
    nusoap_base::debug() in nusoap.php
    -
    adds debug data to the instance debug string with formatting
    -
    -
    - Method - debug -
    -
    -
    nusoap_wsdlcache::debug() in class.wsdlcache.php
    -
    adds debug data to the class level debug string
    -
    -
    - Method - decode -
    -
    -
    soapval::decode() in nusoap.php
    -
    decodes a soapval object into a PHP native type
    -
    -
    - Method - decodeChunked -
    -
    - -
    decode a string that is encoded w/ "chunked' transfer encoding as defined in RFC2068 19.4.6
    -
    -
    - Method - decodeSimple -
    -
    - -
    decodes simple types into PHP variables
    -
    -
    - Method - decodeUTF8 -
    -
    - -
    -
    - -
    -
    e
    - -
    -
    -
    -
    - Variable - $elements -
    -
    - -
    -
    - Variable - $elementStack -
    -
    - -
    -
    - Variable - $element_ns -
    -
    -
    soapval::$element_ns in nusoap.php
    -
    The XML element namespace (string or false)
    -
    -
    - Variable - $enclosingNamespaces -
    -
    - -
    -
    - Variable - $encoding -
    -
    - -
    -
    - Variable - $endpoint -
    -
    - -
    -
    - Variable - $endpoint -
    -
    -
    wsdl::$endpoint in nusoap.php
    -
    -
    - Variable - $endpointType -
    -
    - -
    -
    - Variable - $error_str -
    -
    - -
    Current error string (manipulated by getError/setError)
    -
    -
    - Variable - $externalWSDLURL -
    -
    - -
    URL for WSDL (if one)
    -
    -
    - Method - end_element -
    -
    -
    wsdl::end_element() in nusoap.php
    -
    end-element handler
    -
    -
    - Method - end_element -
    -
    - -
    end-element handler
    -
    -
    - Method - expandEntities -
    -
    - -
    expands entities, e.g. changes '<' to '&lt;'.
    -
    -
    - Method - expandQname -
    -
    - -
    expands (changes prefix to namespace) a qualified name
    -
    -
    - -
    -
    f
    - -
    -
    -
    -
    - Variable - $fault -
    -
    -
    nusoap_parser::$fault in nusoap.php
    -
    -
    - Variable - $fault -
    -
    -
    nusoap_client::$fault in nusoap.php
    -
    -
    - Variable - $fault -
    -
    -
    nusoap_server::$fault in nusoap.php
    -
    SOAP fault for response (or false)
    -
    -
    - Variable - $faultactor -
    -
    - -
    The fault actor
    -
    -
    - Variable - $faultcode -
    -
    - -
    The fault code (client|server)
    -
    -
    - Variable - $faultcode -
    -
    - -
    -
    - Variable - $faultdetail -
    -
    - -
    The fault detail, typically a string or array of string
    -
    -
    - Variable - $faultdetail -
    -
    - -
    -
    - Variable - $faultstring -
    -
    - -
    The fault string, a description of the fault
    -
    -
    - Variable - $faultstring -
    -
    - -
    -
    - Variable - $fault_code -
    -
    - -
    -
    - Variable - $fault_detail -
    -
    - -
    -
    - Variable - $fault_str -
    -
    - -
    -
    - Variable - $forceEndpoint -
    -
    - -
    -
    - Variable - $fplock -
    -
    -
    nusoap_wsdlcache::$fplock in class.wsdlcache.php
    -
    -
    - Method - fault -
    -
    - -
    Specify a fault to be returned to the client.
    -
    -
    - Method - fetchWSDL -
    -
    -
    wsdl::fetchWSDL() in nusoap.php
    -
    fetches the WSDL document and parses it
    -
    -
    - Method - formatDump -
    -
    - -
    formats a string to be inserted into an HTML stream
    -
    -
    - -
    -
    g
    - -
    -
    -
    -
    - Method - get -
    -
    -
    nusoap_wsdlcache::get() in class.wsdlcache.php
    -
    gets a wsdl instance from the cache
    -
    -
    - Method - getAttachments -
    -
    - -
    gets the MIME attachments from the current response.
    -
    -
    - Method - getAttachments -
    -
    - -
    gets the MIME attachments from the current request.
    -
    -
    - Method - getBindingData -
    -
    - -
    -
    - Method - getCookies -
    -
    - -
    gets all Cookies
    -
    -
    - Method - getCookiesForRequest -
    -
    - -
    sort out cookies for the current request
    -
    -
    - Method - getDebug -
    -
    - -
    gets the current debug data for this instance
    -
    -
    - Method - getDebugAsXMLComment -
    -
    - -
    gets the current debug data for this instance as an XML comment this may change the contents of the debug data
    -
    -
    - Method - getDebugLevel -
    -
    - -
    gets the debug level for this instance
    -
    -
    - Method - getDefaultRpcParams -
    -
    - -
    gets the default RPC parameter setting.
    -
    -
    - Method - getError -
    -
    - -
    returns error string if present
    -
    -
    - Method - getGlobalDebugLevel -
    -
    - -
    gets the global debug level, which applies to future instances
    -
    -
    - Method - getHeader -
    -
    - -
    get the SOAP response Header (parsed)
    -
    -
    - Method - getHeaders -
    -
    - -
    get the SOAP response headers (namespace resolution incomplete)
    -
    -
    - Method - getHeaders -
    -
    - -
    get the unparsed SOAP Header
    -
    -
    - Method - getHTTPBody -
    -
    - -
    gets the HTTP body for the current response.
    -
    -
    - Method - getHTTPBody -
    -
    - -
    gets the HTTP body for the current response.
    -
    -
    - Method - getHTTPBody -
    -
    - -
    gets the HTTP body for the current request.
    -
    -
    - Method - getHTTPBody -
    -
    - -
    gets the HTTP body for the current request.
    -
    -
    - Method - getHTTPContentType -
    -
    - -
    gets the HTTP content type for the current response.
    -
    -
    - Method - getHTTPContentType -
    -
    - -
    gets the HTTP content type for the current request.
    -
    -
    - Method - getHTTPContentType -
    -
    - -
    gets the HTTP content type for the current response.
    -
    -
    - Method - getHTTPContentType -
    -
    - -
    gets the HTTP content type for the current request.
    -
    -
    - Method - getHTTPContentTypeCharset -
    -
    - -
    gets the HTTP content type charset for the current request.
    -
    -
    - Method - getHTTPContentTypeCharset -
    -
    - -
    gets the HTTP content type charset for the current response.
    -
    -
    - Method - getHTTPContentTypeCharset -
    -
    - -
    gets the HTTP content type charset for the current request.
    -
    -
    - Method - getHTTPContentTypeCharset -
    -
    - -
    gets the HTTP content type charset for the current response.
    -
    -
    - Method - getLocalPart -
    -
    - -
    returns the local part of a prefixed string returns the original string, if not prefixed
    -
    -
    - Method - getmicrotime -
    -
    - -
    returns the time in ODBC canonical form with microseconds
    -
    -
    - Method - getNamespaceFromPrefix -
    -
    - -
    pass it a prefix, it returns a namespace
    -
    -
    - Method - getOperationData -
    -
    - -
    returns an associative array of data necessary for calling an operation
    -
    -
    - Method - getOperationData -
    -
    - -
    get available data pertaining to an operation
    -
    -
    - Method - getOperationDataForSoapAction -
    -
    - -
    returns an associative array of data necessary for calling an operation
    -
    -
    - Method - getOperations -
    -
    -
    wsdl::getOperations() in nusoap.php
    -
    returns an assoc array of operation names => operation data
    -
    -
    - Method - getPHPType -
    -
    - -
    get the PHP type of a user defined type in the schema
    -
    -
    - Method - getPrefix -
    -
    - -
    returns the prefix part of a prefixed string returns false, if not prefixed
    -
    -
    - Method - getPrefixFromNamespace -
    -
    - -
    returns the prefix for a given namespace (or prefix) or false if no prefixes registered for the given namespace
    -
    -
    - Method - getProxy -
    -
    - -
    dynamically creates an instance of a proxy class, allowing user to directly call methods from wsdl
    -
    -
    - Method - getProxyClassCode -
    -
    - -
    dynamically creates proxy class code
    -
    -
    - Method - getResponse -
    -
    - -
    gets the SOAP response via HTTP[S]
    -
    -
    - Method - getTypeDef -
    -
    - -
    returns an associative array of information about a given type returns false if no type exists by the given name
    -
    -
    - Method - getTypeDef -
    -
    -
    wsdl::getTypeDef() in nusoap.php
    -
    returns an array of information about a given type returns false if no type exists by the given name
    -
    -
    - Method - get_response -
    -
    - -
    get the parsed message (SOAP Body)
    -
    -
    - Method - get_soapbody -
    -
    - -
    get the parsed SOAP Body (NULL if there was none)
    -
    -
    - Method - get_soapheader -
    -
    - -
    get the parsed SOAP Header (NULL if there was none)
    -
    -
    - -
    -
    h
    - -
    -
    -
    -
    - Variable - $headers -
    -
    - -
    HTTP headers of request
    -
    -
    - Variable - $host -
    -
    - -
    -
    - Variable - $http_encoding -
    -
    - -
    -
    - -
    -
    i
    - -
    -
    -
    -
    - Variable - $ids -
    -
    -
    nusoap_parser::$ids in nusoap.php
    -
    -
    - Variable - $import -
    -
    -
    wsdl::$import in nusoap.php
    -
    -
    - Variable - $imports -
    -
    - -
    -
    - Variable - $incoming_cookies -
    -
    - -
    -
    - Variable - $incoming_headers -
    -
    - -
    -
    - Variable - $incoming_payload -
    -
    - -
    -
    - Method - invoke_method -
    -
    - -
    invokes a PHP function for the requested SOAP method
    -
    -
    - Method - io_method -
    -
    - -
    gets the I/O method to use
    -
    -
    - Method - isArraySimpleOrStruct -
    -
    - -
    detect if array is a simple array or a struct (associative array)
    -
    -
    - Function - iso8601_to_timestamp -
    -
    - -
    convert ISO 8601 compliant date string to unix timestamp
    -
    -
    - Method - isSkippableCurlHeader -
    -
    - -
    Test if the given string starts with a header that is to be skipped.
    -
    -
    - -
    -
    l
    - -
    -
    -
    -
    - Method - loadWSDL -
    -
    - -
    instantiate wsdl object and parse wsdl file
    -
    -
    - -
    -
    m
    - -
    -
    -
    -
    - Variable - $message -
    -
    - -
    -
    - Variable - $message -
    -
    -
    wsdl::$message in nusoap.php
    -
    -
    - Variable - $message -
    -
    - -
    -
    - Variable - $messages -
    -
    -
    wsdl::$messages in nusoap.php
    -
    -
    - Variable - $method -
    -
    - -
    -
    - Variable - $methodname -
    -
    - -
    name of method requested
    -
    -
    - Variable - $methodparams -
    -
    - -
    method parameters from request
    -
    -
    - Variable - $methodreturn -
    -
    - -
    method return value to place in response
    -
    -
    - Variable - $methodreturnisliteralxml -
    -
    - -
    whether $methodreturn is a string of literal XML
    -
    -
    - Variable - $methodURI -
    -
    - -
    requested method namespace URI
    -
    -
    - Variable - $mimeContentType -
    -
    - -
    -
    - Variable - $mimeContentType -
    -
    - -
    -
    - Variable - $multirefs -
    -
    - -
    -
    - -
    -
    n
    - -
    -
    -
    -
    - Variable - $name -
    -
    -
    soapval::$name in nusoap.php
    -
    The XML element name
    -
    -
    - Variable - $namespaces -
    -
    - -
    -
    - Variable - $namespaces -
    -
    - -
    namespaces in an array of prefix => uri
    -
    -
    - Page - nusoapmime.php -
    -
    -
    nusoapmime.php in nusoapmime.php
    -
    -
    - Class - nusoapservermime -
    -
    -
    nusoapservermime in nusoapmime.php
    -
    nusoap_server_mime server supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
    -
    -
    - Method - nusoap_base -
    -
    - -
    constructor
    -
    -
    - Class - nusoap_base -
    -
    -
    nusoap_base in nusoap.php
    -
    nusoap_base
    -
    -
    - Class - nusoap_client -
    -
    -
    nusoap_client in nusoap.php
    -
    [nu]soapclient higher level class for easy usage.
    -
    -
    - Method - nusoap_client -
    -
    - -
    constructor
    -
    -
    - Class - nusoap_client_mime -
    -
    -
    nusoap_client_mime in nusoapmime.php
    -
    nusoap_client_mime client supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
    -
    -
    - Class - nusoap_fault -
    -
    -
    nusoap_fault in nusoap.php
    -
    Contains information for a SOAP fault.
    -
    -
    - Method - nusoap_fault -
    -
    - -
    constructor
    -
    -
    - Class - nusoap_parser -
    -
    -
    nusoap_parser in nusoap.php
    -
    nusoap_parser class parses SOAP XML messages into native PHP values
    -
    -
    - Method - nusoap_parser -
    -
    - -
    constructor that actually does the parsing
    -
    -
    - Page - nusoap.php -
    -
    -
    nusoap.php in nusoap.php
    -
    -
    - Method - nusoap_server -
    -
    - -
    constructor the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
    -
    -
    - Class - nusoap_server -
    -
    -
    nusoap_server in nusoap.php
    -
    nusoap_server allows the user to create a SOAP server that is capable of receiving messages and returning responses
    -
    -
    - Class - nusoap_server_mime -
    -
    -
    nusoap_server_mime in nusoapmime.php
    -
    nusoap_server_mime server supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
    -
    -
    - Class - nusoap_wsdlcache -
    -
    -
    nusoap_wsdlcache in class.wsdlcache.php
    -
    caches instances of the wsdl class
    -
    -
    - Method - nusoap_wsdlcache -
    -
    - -
    constructor
    -
    -
    - Class - nusoap_xmlschema -
    -
    -
    nusoap_xmlschema in nusoap.php
    -
    parses an XML Schema, allows access to it's data, other utility methods.
    -
    -
    - Method - nusoap_xmlschema -
    -
    - -
    constructor
    -
    -
    - -
    -
    o
    - -
    -
    -
    -
    - Variable - $opData -
    -
    -
    wsdl::$opData in nusoap.php
    -
    -
    - Variable - $operations -
    -
    - -
    assoc array of operations => opData; operations are added by the register()
    -
    -
    - Variable - $operations -
    -
    - -
    -
    - Variable - $outgoing_headers -
    -
    - -
    -
    - Variable - $outgoing_headers -
    -
    - -
    HTTP headers of response
    -
    -
    - Variable - $outgoing_payload -
    -
    - -
    -
    - Method - obtainMutex -
    -
    -
    nusoap_wsdlcache::obtainMutex() in class.wsdlcache.php
    -
    obtains the local mutex
    -
    -
    - -
    -
    p
    - -
    -
    -
    -
    - Variable - $parent -
    -
    - -
    -
    - Variable - $parser -
    -
    -
    wsdl::$parser in nusoap.php
    -
    -
    - Variable - $parser -
    -
    - -
    -
    - Variable - $password -
    -
    -
    wsdl::$password in nusoap.php
    -
    -
    - Variable - $password -
    -
    - -
    -
    - Variable - $password -
    -
    - -
    -
    - Variable - $path -
    -
    - -
    -
    - Variable - $persistentConnection -
    -
    - -
    -
    - Variable - $persistentConnection -
    -
    - -
    -
    - Variable - $port -
    -
    - -
    -
    - Variable - $portName -
    -
    - -
    -
    - Variable - $ports -
    -
    -
    wsdl::$ports in nusoap.php
    -
    -
    - Variable - $portTypes -
    -
    -
    wsdl::$portTypes in nusoap.php
    -
    -
    - Variable - $position -
    -
    - -
    -
    - Variable - $position -
    -
    - -
    -
    - Variable - $position -
    -
    -
    wsdl::$position in nusoap.php
    -
    -
    - Variable - $protocol_version -
    -
    - -
    -
    - Variable - $proxy -
    -
    - -
    -
    - Variable - $proxyhost -
    -
    -
    wsdl::$proxyhost in nusoap.php
    -
    -
    - Variable - $proxyhost -
    -
    - -
    -
    - Variable - $proxypassword -
    -
    - -
    -
    - Variable - $proxypassword -
    -
    -
    wsdl::$proxypassword in nusoap.php
    -
    -
    - Variable - $proxyport -
    -
    -
    wsdl::$proxyport in nusoap.php
    -
    -
    - Variable - $proxyport -
    -
    - -
    -
    - Variable - $proxyusername -
    -
    - -
    -
    - Variable - $proxyusername -
    -
    -
    wsdl::$proxyusername in nusoap.php
    -
    -
    - Method - parametersMatchWrapped -
    -
    - -
    determine whether a set of parameters are unwrapped when they are expect to be wrapped, Microsoft-style.
    -
    -
    - Method - parseCookie -
    -
    - -
    parse an incoming Cookie into it's parts
    -
    -
    - Method - parseFile -
    -
    - -
    parse an XML file
    -
    -
    - Method - parseRequest -
    -
    - -
    processes SOAP message received from client
    -
    -
    - Method - parseRequest -
    -
    - -
    processes SOAP message received from client
    -
    -
    - Method - parseResponse -
    -
    - -
    processes SOAP message returned from server
    -
    -
    - Method - parseResponse -
    -
    - -
    processes SOAP message returned from server
    -
    -
    - Method - parseString -
    -
    - -
    parse an XML string
    -
    -
    - Method - parseWSDL -
    -
    -
    wsdl::parseWSDL() in nusoap.php
    -
    parses the wsdl document
    -
    -
    - Method - parse_http_headers -
    -
    - -
    parses HTTP request headers.
    -
    -
    - Method - parse_request -
    -
    - -
    parses a request
    -
    -
    - Method - put -
    -
    -
    nusoap_wsdlcache::put() in class.wsdlcache.php
    -
    adds a wsdl instance to the cache
    -
    -
    - -
    -
    r
    - -
    -
    -
    -
    - Variable - $request -
    -
    - -
    HTTP request
    -
    -
    - Variable - $request -
    -
    - -
    -
    - Variable - $requestAttachments -
    -
    - -
    -
    - Variable - $requestAttachments -
    -
    - -
    -
    - Variable - $requestHeader -
    -
    - -
    SOAP Headers from request (parsed)
    -
    -
    - Variable - $requestHeaders -
    -
    - -
    SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
    -
    -
    - Variable - $requestHeaders -
    -
    - -
    -
    - Variable - $requestSOAP -
    -
    - -
    SOAP payload for request (text)
    -
    -
    - Variable - $request_method -
    -
    - -
    -
    - Variable - $response -
    -
    - -
    -
    - Variable - $response -
    -
    - -
    HTTP response
    -
    -
    - Variable - $responseAttachments -
    -
    - -
    -
    - Variable - $responseAttachments -
    -
    - -
    -
    - Variable - $responseData -
    -
    - -
    -
    - Variable - $responseHeader -
    -
    - -
    -
    - Variable - $responseHeaders -
    -
    - -
    -
    - Variable - $responseHeaders -
    -
    - -
    SOAP headers for response (text or array of soapval or associative array)
    -
    -
    - Variable - $responseHeaders -
    -
    - -
    -
    - Variable - $responseSOAP -
    -
    - -
    SOAP payload for response (text)
    -
    -
    - Variable - $response_status_line -
    -
    - -
    -
    - Variable - $response_timeout -
    -
    - -
    -
    - Variable - $response_timeout -
    -
    - -
    -
    - Variable - $result -
    -
    - -
    text indication of result (for debugging)
    -
    -
    - Variable - $revision -
    -
    - -
    CVS revision for HTTP headers.
    -
    -
    - Variable - $root_header -
    -
    - -
    -
    - Variable - $root_struct -
    -
    - -
    -
    - Variable - $root_struct_name -
    -
    - -
    -
    - Variable - $root_struct_namespace -
    -
    - -
    -
    - Method - register -
    -
    - -
    register a service function with the server
    -
    -
    - Method - releaseMutex -
    -
    -
    nusoap_wsdlcache::releaseMutex() in class.wsdlcache.php
    -
    releases the local mutex
    -
    -
    - Method - remove -
    -
    -
    nusoap_wsdlcache::remove() in class.wsdlcache.php
    -
    removes a wsdl instance from the cache
    -
    -
    - -
    -
    s
    - -
    -
    -
    -
    - Variable - $schema -
    -
    - -
    -
    - Variable - $schemaInfo -
    -
    - -
    -
    - Variable - $schemas -
    -
    -
    wsdl::$schemas in nusoap.php
    -
    -
    - Variable - $schemaTargetNamespace -
    -
    - -
    -
    - Variable - $scheme -
    -
    - -
    -
    - Variable - $simpleTypes -
    -
    - -
    -
    - Variable - $simpleTypeStack -
    -
    - -
    -
    - Variable - $SOAPAction -
    -
    - -
    SOAP Action from request
    -
    -
    - Variable - $soapheader -
    -
    - -
    -
    - Variable - $soapresponse -
    -
    - -
    -
    - Variable - $soap_defencoding -
    -
    - -
    charset encoding for outgoing messages
    -
    -
    - Variable - $status -
    -
    -
    wsdl::$status in nusoap.php
    -
    -
    - Variable - $status -
    -
    - -
    -
    - Method - schemaCharacterData -
    -
    - -
    element content handler
    -
    -
    - Method - schemaEndElement -
    -
    - -
    end-element handler
    -
    -
    - Method - schemaStartElement -
    -
    - -
    start-element handler
    -
    -
    - Method - send -
    -
    -
    nusoap_client::send() in nusoap.php
    -
    send the SOAP message
    -
    -
    - Method - send -
    -
    - -
    sends the SOAP request and gets the SOAP response via HTTP[S]
    -
    -
    - Method - sendHTTPS -
    -
    - -
    sends the SOAP request and gets the SOAP response via HTTPS using CURL
    -
    -
    - Method - sendRequest -
    -
    - -
    sends the SOAP request via HTTP[S]
    -
    -
    - Method - send_response -
    -
    - -
    sends an HTTP response
    -
    -
    - Method - serialize -
    -
    -
    soapval::serialize() in nusoap.php
    -
    return serialized value
    -
    -
    - Method - serialize -
    -
    - -
    serialize a fault
    -
    -
    - Method - serialize -
    -
    -
    wsdl::serialize() in nusoap.php
    -
    serialize the parsed wsdl
    -
    -
    - Method - serializeComplexTypeAttributes -
    -
    - -
    serializes the attributes for a complexType
    -
    -
    - Method - serializeComplexTypeElements -
    -
    - -
    serializes the elements for a complexType
    -
    -
    - Method - serializeEnvelope -
    -
    - -
    serializes a message
    -
    -
    - Method - serializeParameters -
    -
    - -
    serialize a PHP value according to a WSDL message definition
    -
    -
    - Method - serializeRPCParameters -
    -
    - -
    serialize PHP values according to a WSDL message definition contrary to the method name, this is not limited to RPC
    -
    -
    - Method - serializeSchema -
    -
    - -
    serialize the schema
    -
    -
    - Method - serializeType -
    -
    -
    wsdl::serializeType() in nusoap.php
    -
    serializes a PHP value according a given type definition
    -
    -
    - Method - serializeTypeDef -
    -
    - -
    returns a sample serialization of a given type, or false if no type by the given name
    -
    -
    - Method - serialize_return -
    -
    - -
    serializes the return value from a PHP function into a full SOAP Envelope
    -
    -
    - Method - serialize_val -
    -
    - -
    serializes PHP values in accordance w/ section 5. Type information is not serialized if $use == 'literal'.
    -
    -
    - Method - service -
    -
    - -
    processes request and returns response
    -
    -
    - Method - setContentType -
    -
    - -
    sets the content-type for the SOAP message to be sent
    -
    -
    - Method - setCookie -
    -
    - -
    adds a new Cookie into $this->cookies array
    -
    -
    - Method - setCredentials -
    -
    - -
    if authenticating, set user credentials here
    -
    -
    - Method - setCredentials -
    -
    - -
    if authenticating, set user credentials here
    -
    -
    - Method - setCredentials -
    -
    - -
    if authenticating, set user credentials here
    -
    -
    - Method - setCurlOption -
    -
    - -
    sets a cURL option
    -
    -
    - Method - setCurlOption -
    -
    - -
    sets user-specified cURL options
    -
    -
    - Method - setDebugLevel -
    -
    - -
    sets the debug level for this instance
    -
    -
    - Method - setDefaultRpcParams -
    -
    - -
    sets the default RPC parameter setting.
    -
    -
    - Method - setEncoding -
    -
    - -
    use http encoding
    -
    -
    - Method - setEndpoint -
    -
    - -
    sets the SOAP endpoint, which can override WSDL
    -
    -
    - Method - setError -
    -
    - -
    sets error string
    -
    -
    - Method - setGlobalDebugLevel -
    -
    - -
    sets the global debug level, which applies to future instances
    -
    -
    - Method - setHeader -
    -
    - -
    sets an HTTP header
    -
    -
    - Method - setHeaders -
    -
    - -
    set the SOAP headers
    -
    -
    - Method - setHTTPEncoding -
    -
    - -
    use HTTP encoding
    -
    -
    - Method - setHTTPProxy -
    -
    - -
    set proxy info here
    -
    -
    - Method - setProxy -
    -
    - -
    set proxy info here
    -
    -
    - Method - setSOAPAction -
    -
    - -
    set the soapaction value
    -
    -
    - Method - setURL -
    -
    - -
    sets the URL to which to connect
    -
    -
    - Method - setUseCURL -
    -
    - -
    Set whether to try to use cURL connections if possible
    -
    -
    - Class - soapclient -
    -
    -
    soapclient in nusoap.php
    -
    For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
    -
    -
    - Class - soapclientmime -
    -
    -
    soapclientmime in nusoapmime.php
    -
    nusoap_client_mime client supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
    -
    -
    - Method - soapval -
    -
    -
    soapval::soapval() in nusoap.php
    -
    constructor
    -
    -
    - Class - soapval -
    -
    -
    soapval in nusoap.php
    -
    For creating serializable abstractions of native PHP types. This class
    -
    -
    - Class - soap_fault -
    -
    -
    soap_fault in nusoap.php
    -
    Backward compatibility
    -
    -
    - Class - soap_parser -
    -
    -
    soap_parser in nusoap.php
    -
    Backward compatibility
    -
    -
    - Class - soap_server -
    -
    -
    soap_server in nusoap.php
    -
    Backward compatibility
    -
    -
    - Method - soap_transport_http -
    -
    - -
    constructor
    -
    -
    - Class - soap_transport_http -
    -
    -
    soap_transport_http in nusoap.php
    -
    transport class for sending/receiving data via HTTP and HTTPS NOTE: PHP must be compiled with the CURL extension for HTTPS support
    -
    -
    - Method - start_element -
    -
    -
    wsdl::start_element() in nusoap.php
    -
    start-element handler
    -
    -
    - Method - start_element -
    -
    - -
    start-element handler
    -
    -
    - -
    -
    t
    - -
    -
    -
    -
    - Variable - $timeout -
    -
    -
    wsdl::$timeout in nusoap.php
    -
    -
    - Variable - $timeout -
    -
    - -
    -
    - Variable - $title -
    -
    -
    nusoap_base::$title in nusoap.php
    -
    Identification for HTTP headers.
    -
    -
    - Variable - $type -
    -
    -
    soapval::$type in nusoap.php
    -
    The XML type name (string or false)
    -
    -
    - Variable - $typemap -
    -
    -
    nusoap_base::$typemap in nusoap.php
    -
    XML Schema types in an array of uri => (array of xml type => php type) is this legacy yet? no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
    -
    -
    - Variable - $type_ns -
    -
    -
    soapval::$type_ns in nusoap.php
    -
    The XML type namespace (string or false)
    -
    -
    - Function - timestamp_to_iso8601 -
    -
    - -
    convert unix timestamp to ISO 8601 compliant date string
    -
    -
    - Method - typeToForm -
    -
    - -
    returns HTML form elements that allow a user to enter values for creating an instance of the given type.
    -
    -
    - -
    -
    u
    - -
    -
    -
    -
    - Variable - $uri -
    -
    - -
    -
    - Variable - $url -
    -
    - -
    -
    - Variable - $usedNamespaces -
    -
    - -
    namespaces used in the current context, e.g. during serialization
    -
    -
    - Variable - $username -
    -
    - -
    -
    - Variable - $username -
    -
    -
    wsdl::$username in nusoap.php
    -
    -
    - Variable - $username -
    -
    - -
    -
    - Variable - $useSOAPAction -
    -
    - -
    -
    - Variable - $use_curl -
    -
    - -
    -
    - Variable - $use_curl -
    -
    -
    wsdl::$use_curl in nusoap.php
    -
    -
    - Variable - $use_curl -
    -
    - -
    -
    - Method - unsetHeader -
    -
    - -
    unsets an HTTP header
    -
    -
    - Method - UpdateCookies -
    -
    - -
    updates the current cookies with a new set
    -
    -
    - Method - useHTTPPersistentConnection -
    -
    - -
    use HTTP persistent connections if possible
    -
    -
    - Method - usePersistentConnection -
    -
    - -
    specifies that an HTTP persistent connection should be used
    -
    -
    - Function - usleepWindows -
    -
    -
    usleepWindows() in nusoap.php
    -
    sleeps some number of microseconds
    -
    -
    - -
    -
    v
    - -
    -
    -
    -
    - Variable - $value -
    -
    -
    soapval::$value in nusoap.php
    -
    The PHP value
    -
    -
    - Variable - $version -
    -
    -
    nusoap_base::$version in nusoap.php
    -
    Version for HTTP headers.
    -
    -
    - Method - varDump -
    -
    - -
    Returns a string with the output of var_dump
    -
    -
    - Method - verify_method -
    -
    - -
    takes the value that was created by parsing the request and compares to the method's signature, if available.
    -
    -
    - -
    -
    w
    - -
    -
    -
    -
    - Variable - $wsdl -
    -
    -
    wsdl::$wsdl in nusoap.php
    -
    -
    - Variable - $wsdl -
    -
    -
    nusoap_server::$wsdl in nusoap.php
    -
    wsdl instance (if one)
    -
    -
    - Method - webDescription -
    -
    - -
    prints html description of services
    -
    -
    - Method - wsdl -
    -
    -
    wsdl::wsdl() in nusoap.php
    -
    constructor
    -
    -
    - Class - wsdl -
    -
    -
    wsdl in nusoap.php
    -
    parses a WSDL file, allows access to it's data, other utility methods.
    -
    -
    - Class - wsdlcache -
    -
    -
    wsdlcache in class.wsdlcache.php
    -
    For backward compatibility
    -
    -
    - -
    -
    x
    - -
    -
    -
    -
    - Variable - $xml -
    -
    -
    nusoap_parser::$xml in nusoap.php
    -
    -
    - Variable - $xml -
    -
    - -
    -
    - Variable - $xmlEntities -
    -
    - -
    XML entities to convert
    -
    -
    - Variable - $XMLSchemaVersion -
    -
    - -
    set schema version
    -
    -
    - Variable - $xml_encoding -
    -
    - -
    character set encoding of incoming (request) messages
    -
    -
    - Variable - $xml_encoding -
    -
    - -
    -
    - Variable - $xml_encoding -
    -
    - -
    -
    - Method - xdebug -
    -
    - -
    adds debug data to the clas level debug string
    -
    -
    - Class - XMLSchema -
    -
    -
    XMLSchema in nusoap.php
    -
    Backward compatibility
    -
    -
    - -
    - a - b - c - d - e - f - g - h - i - l - m - n - o - p - r - s - t - u - v - w - x - _ -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/errors.html b/lib/nusoap/docs/docs/errors.html deleted file mode 100644 index 104e1de33..000000000 --- a/lib/nusoap/docs/docs/errors.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - phpDocumentor Parser Errors and Warnings - - - - - Post-parsing
    -nusoap.php
    -nusoapmime.php
    - -

    class.wsdlcache.php

    -

    Warnings:


    -Warning on line 17 - no @package tag was used in a DocBlock for class nusoap_wsdlcache
    -Warning on line 206 - no @package tag was used in a DocBlock for class wsdlcache
    -Warning on line 208 - File "C:\nusoap\lib\class.wsdlcache.php" has no page-level DocBlock, use @package in the first DocBlock to create one
    - -

    nusoap.php

    -

    Warnings:


    -Warning on line 84 - no @package tag was used in a DocBlock for class nusoap_base
    -Warning on line 1006 - no @package tag was used in a DocBlock for class nusoap_fault
    -Warning on line 1078 - no @package tag was used in a DocBlock for class soap_fault
    -Warning on line 1094 - no @package tag was used in a DocBlock for class nusoap_xmlschema
    -Warning on line 2047 - no @package tag was used in a DocBlock for class XMLSchema
    -Warning on line 2065 - no @package tag was used in a DocBlock for class soapval
    -Warning on line 2167 - no @package tag was used in a DocBlock for class soap_transport_http
    -Warning on line 3472 - no @package tag was used in a DocBlock for class nusoap_server
    -Warning on line 4579 - no @package tag was used in a DocBlock for class soap_server
    -Warning on line 4595 - no @package tag was used in a DocBlock for class wsdl
    -Warning on line 6445 - no @package tag was used in a DocBlock for class nusoap_parser
    -Warning on line 7069 - no @package tag was used in a DocBlock for class soap_parser
    -Warning on line 7096 - no @package tag was used in a DocBlock for class nusoap_client
    -Warning on line 8054 - no @package tag was used in a DocBlock for class soapclient
    -Warning on line 8057 - File "C:\nusoap\lib\nusoap.php" has no page-level DocBlock, use @package in the first DocBlock to create one
    - -

    nusoapmime.php

    -

    Warnings:


    -Warning on line 53 - no @package tag was used in a DocBlock for class nusoap_client_mime
    -Warning on line 270 - no @package tag was used in a DocBlock for class soapclientmime
    -Warning on line 283 - no @package tag was used in a DocBlock for class nusoap_server_mime
    -Warning on line 497 - no @package tag was used in a DocBlock for class nusoapservermime
    -Warning on line 500 - File "C:\nusoap\lib\nusoapmime.php" has no page-level DocBlock, use @package in the first DocBlock to create one
    -

    - Documentation generated on Mon, 26 Apr 2010 16:17:11 -0400 by phpDocumentor 1.3.0RC3 -

    - - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/index.html b/lib/nusoap/docs/docs/index.html deleted file mode 100644 index 90a860488..000000000 --- a/lib/nusoap/docs/docs/index.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - phpDocumentor 1.3.0 Manual - - - - - - - - - - - <H2>Frame Alert</H2> - <P>This document is designed to be viewed using the frames feature. - If you see this message, you are using a non-frame-capable web client.</P> - - - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/li_nusoap.html b/lib/nusoap/docs/docs/li_nusoap.html deleted file mode 100644 index 7cad615f6..000000000 --- a/lib/nusoap/docs/docs/li_nusoap.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - -
    nusoap
    - -

    phpDocumentor v 1.3.0RC3

    - - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/media/CVS/Entries b/lib/nusoap/docs/docs/media/CVS/Entries deleted file mode 100644 index e3935f8fe..000000000 --- a/lib/nusoap/docs/docs/media/CVS/Entries +++ /dev/null @@ -1,3 +0,0 @@ -D/images//// -/banner.css/1.1/Mon Apr 26 19:16:48 2010// -/stylesheet.css/1.1/Mon Apr 26 19:16:48 2010// diff --git a/lib/nusoap/docs/docs/media/CVS/Repository b/lib/nusoap/docs/docs/media/CVS/Repository deleted file mode 100644 index 63228ddc4..000000000 --- a/lib/nusoap/docs/docs/media/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -docs/media diff --git a/lib/nusoap/docs/docs/media/CVS/Root b/lib/nusoap/docs/docs/media/CVS/Root deleted file mode 100644 index 38e068369..000000000 --- a/lib/nusoap/docs/docs/media/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -:ext:snichol@nusoap.cvs.sourceforge.net:/cvsroot/nusoap diff --git a/lib/nusoap/docs/docs/media/banner.css b/lib/nusoap/docs/docs/media/banner.css deleted file mode 100644 index 032b037f4..000000000 --- a/lib/nusoap/docs/docs/media/banner.css +++ /dev/null @@ -1,33 +0,0 @@ -body -{ - background-color: #EEEEEE; - margin: 0px; - padding: 0px; -} - -/* Banner (top bar) classes */ - -.banner { } - -.banner-menu -{ - text-align: right; - clear: both; - padding: .5em; - border-top: 2px solid #AAAAAA; -} - -.banner-title -{ - text-align: right; - font-size: 20pt; - font-weight: bold; - margin: .2em; -} - -.package-selector -{ - background-color: #DDDDDD; - border: 1px solid #AAAAAA; - color: #000090; -} diff --git a/lib/nusoap/docs/docs/media/images/AbstractClass.png b/lib/nusoap/docs/docs/media/images/AbstractClass.png deleted file mode 100644 index afa9d1d92..000000000 Binary files a/lib/nusoap/docs/docs/media/images/AbstractClass.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/AbstractClass_logo.png b/lib/nusoap/docs/docs/media/images/AbstractClass_logo.png deleted file mode 100644 index 8f65c390e..000000000 Binary files a/lib/nusoap/docs/docs/media/images/AbstractClass_logo.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/AbstractMethod.png b/lib/nusoap/docs/docs/media/images/AbstractMethod.png deleted file mode 100644 index 605ccbe58..000000000 Binary files a/lib/nusoap/docs/docs/media/images/AbstractMethod.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/AbstractPrivateClass.png b/lib/nusoap/docs/docs/media/images/AbstractPrivateClass.png deleted file mode 100644 index 53d76c636..000000000 Binary files a/lib/nusoap/docs/docs/media/images/AbstractPrivateClass.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/AbstractPrivateClass_logo.png b/lib/nusoap/docs/docs/media/images/AbstractPrivateClass_logo.png deleted file mode 100644 index 4e68f570d..000000000 Binary files a/lib/nusoap/docs/docs/media/images/AbstractPrivateClass_logo.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/AbstractPrivateMethod.png b/lib/nusoap/docs/docs/media/images/AbstractPrivateMethod.png deleted file mode 100644 index 41cc9f021..000000000 Binary files a/lib/nusoap/docs/docs/media/images/AbstractPrivateMethod.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/CVS/Entries b/lib/nusoap/docs/docs/media/images/CVS/Entries deleted file mode 100644 index 52a9352d3..000000000 --- a/lib/nusoap/docs/docs/media/images/CVS/Entries +++ /dev/null @@ -1,46 +0,0 @@ -/AbstractClass.png/1.1/Mon Apr 26 19:16:48 2010// -/AbstractClass_logo.png/1.1/Mon Apr 26 19:16:48 2010// -/AbstractMethod.png/1.1/Mon Apr 26 19:16:48 2010// -/AbstractPrivateClass.png/1.1/Mon Apr 26 19:16:48 2010// -/AbstractPrivateClass_logo.png/1.1/Mon Apr 26 19:16:48 2010// -/AbstractPrivateMethod.png/1.1/Mon Apr 26 19:16:48 2010// -/Class.png/1.1/Mon Apr 26 19:16:48 2010// -/Class_logo.png/1.1/Mon Apr 26 19:16:48 2010// -/Constant.png/1.1/Mon Apr 26 19:16:48 2010// -/Constructor.png/1.1/Mon Apr 26 19:16:48 2010// -/Destructor.png/1.1/Mon Apr 26 19:16:48 2010// -/Function.png/1.1/Mon Apr 26 19:16:48 2010// -/Global.png/1.1/Mon Apr 26 19:16:48 2010// -/I.png/1.1/Mon Apr 26 19:16:48 2010// -/Index.png/1.1/Mon Apr 26 19:16:48 2010// -/L.png/1.1/Mon Apr 26 19:16:48 2010// -/Lminus.png/1.1/Mon Apr 26 19:16:48 2010// -/Lplus.png/1.1/Mon Apr 26 19:16:48 2010// -/Method.png/1.1/Mon Apr 26 19:16:48 2010// -/Page.png/1.1/Mon Apr 26 19:16:48 2010// -/Page_logo.png/1.1/Mon Apr 26 19:16:48 2010// -/PrivateClass.png/1.1/Mon Apr 26 19:16:48 2010// -/PrivateClass_logo.png/1.1/Mon Apr 26 19:16:48 2010// -/PrivateMethod.png/1.1/Mon Apr 26 19:16:48 2010// -/PrivateVariable.png/1.1/Mon Apr 26 19:16:48 2010// -/T.png/1.1/Mon Apr 26 19:16:48 2010// -/Tminus.png/1.1/Mon Apr 26 19:16:48 2010// -/Tplus.png/1.1/Mon Apr 26 19:16:48 2010// -/Variable.png/1.1/Mon Apr 26 19:16:48 2010// -/blank.png/1.1/Mon Apr 26 19:16:48 2010// -/class_folder.png/1.1/Mon Apr 26 19:16:48 2010// -/empty.png/1.1/Mon Apr 26 19:16:48 2010// -/file.png/1.1/Mon Apr 26 19:16:48 2010// -/folder.png/1.1/Mon Apr 26 19:16:48 2010// -/function_folder.png/1.1/Mon Apr 26 19:16:48 2010// -/next_button.png/1.1/Mon Apr 26 19:16:48 2010// -/next_button_disabled.png/1.1/Mon Apr 26 19:16:48 2010// -/package.png/1.1/Mon Apr 26 19:16:48 2010// -/package_folder.png/1.1/Mon Apr 26 19:16:48 2010// -/previous_button.png/1.1/Mon Apr 26 19:16:48 2010// -/previous_button_disabled.png/1.1/Mon Apr 26 19:16:48 2010// -/private_class_logo.png/1.1/Mon Apr 26 19:16:48 2010// -/tutorial.png/1.1/Mon Apr 26 19:16:48 2010// -/tutorial_folder.png/1.1/Mon Apr 26 19:16:48 2010// -/up_button.png/1.1/Mon Apr 26 19:16:48 2010// -D diff --git a/lib/nusoap/docs/docs/media/images/CVS/Repository b/lib/nusoap/docs/docs/media/images/CVS/Repository deleted file mode 100644 index ee976e2a5..000000000 --- a/lib/nusoap/docs/docs/media/images/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -docs/media/images diff --git a/lib/nusoap/docs/docs/media/images/CVS/Root b/lib/nusoap/docs/docs/media/images/CVS/Root deleted file mode 100644 index 38e068369..000000000 --- a/lib/nusoap/docs/docs/media/images/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -:ext:snichol@nusoap.cvs.sourceforge.net:/cvsroot/nusoap diff --git a/lib/nusoap/docs/docs/media/images/Class.png b/lib/nusoap/docs/docs/media/images/Class.png deleted file mode 100644 index cf548d274..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Class.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/Class_logo.png b/lib/nusoap/docs/docs/media/images/Class_logo.png deleted file mode 100644 index 6f223c479..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Class_logo.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/Constant.png b/lib/nusoap/docs/docs/media/images/Constant.png deleted file mode 100644 index a9c6f28b3..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Constant.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/Constructor.png b/lib/nusoap/docs/docs/media/images/Constructor.png deleted file mode 100644 index 3f16222b4..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Constructor.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/Destructor.png b/lib/nusoap/docs/docs/media/images/Destructor.png deleted file mode 100644 index f28528f08..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Destructor.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/Function.png b/lib/nusoap/docs/docs/media/images/Function.png deleted file mode 100644 index 902fe2580..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Function.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/Global.png b/lib/nusoap/docs/docs/media/images/Global.png deleted file mode 100644 index 7281bd2aa..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Global.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/I.png b/lib/nusoap/docs/docs/media/images/I.png deleted file mode 100644 index e8512fb91..000000000 Binary files a/lib/nusoap/docs/docs/media/images/I.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/Index.png b/lib/nusoap/docs/docs/media/images/Index.png deleted file mode 100644 index 6558ec393..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Index.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/L.png b/lib/nusoap/docs/docs/media/images/L.png deleted file mode 100644 index eb334edae..000000000 Binary files a/lib/nusoap/docs/docs/media/images/L.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/Lminus.png b/lib/nusoap/docs/docs/media/images/Lminus.png deleted file mode 100644 index f7c43c0aa..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Lminus.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/Lplus.png b/lib/nusoap/docs/docs/media/images/Lplus.png deleted file mode 100644 index 848ec2fc3..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Lplus.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/Method.png b/lib/nusoap/docs/docs/media/images/Method.png deleted file mode 100644 index 9b2157845..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Method.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/Page.png b/lib/nusoap/docs/docs/media/images/Page.png deleted file mode 100644 index ffe7986ee..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Page.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/Page_logo.png b/lib/nusoap/docs/docs/media/images/Page_logo.png deleted file mode 100644 index 44ce0b3c6..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Page_logo.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/PrivateClass.png b/lib/nusoap/docs/docs/media/images/PrivateClass.png deleted file mode 100644 index 470e6d568..000000000 Binary files a/lib/nusoap/docs/docs/media/images/PrivateClass.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/PrivateClass_logo.png b/lib/nusoap/docs/docs/media/images/PrivateClass_logo.png deleted file mode 100644 index 590e00640..000000000 Binary files a/lib/nusoap/docs/docs/media/images/PrivateClass_logo.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/PrivateMethod.png b/lib/nusoap/docs/docs/media/images/PrivateMethod.png deleted file mode 100644 index d01f2b314..000000000 Binary files a/lib/nusoap/docs/docs/media/images/PrivateMethod.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/PrivateVariable.png b/lib/nusoap/docs/docs/media/images/PrivateVariable.png deleted file mode 100644 index d76b21d4e..000000000 Binary files a/lib/nusoap/docs/docs/media/images/PrivateVariable.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/T.png b/lib/nusoap/docs/docs/media/images/T.png deleted file mode 100644 index 301732540..000000000 Binary files a/lib/nusoap/docs/docs/media/images/T.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/Tminus.png b/lib/nusoap/docs/docs/media/images/Tminus.png deleted file mode 100644 index 2260e4248..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Tminus.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/Tplus.png b/lib/nusoap/docs/docs/media/images/Tplus.png deleted file mode 100644 index 2c8d8f4fd..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Tplus.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/Variable.png b/lib/nusoap/docs/docs/media/images/Variable.png deleted file mode 100644 index 8e820193c..000000000 Binary files a/lib/nusoap/docs/docs/media/images/Variable.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/blank.png b/lib/nusoap/docs/docs/media/images/blank.png deleted file mode 100644 index cee9cd37a..000000000 Binary files a/lib/nusoap/docs/docs/media/images/blank.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/class_folder.png b/lib/nusoap/docs/docs/media/images/class_folder.png deleted file mode 100644 index 84e9587af..000000000 Binary files a/lib/nusoap/docs/docs/media/images/class_folder.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/empty.png b/lib/nusoap/docs/docs/media/images/empty.png deleted file mode 100644 index d56838651..000000000 Binary files a/lib/nusoap/docs/docs/media/images/empty.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/file.png b/lib/nusoap/docs/docs/media/images/file.png deleted file mode 100644 index 0bb2427f8..000000000 Binary files a/lib/nusoap/docs/docs/media/images/file.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/folder.png b/lib/nusoap/docs/docs/media/images/folder.png deleted file mode 100644 index a2d79f8de..000000000 Binary files a/lib/nusoap/docs/docs/media/images/folder.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/function_folder.png b/lib/nusoap/docs/docs/media/images/function_folder.png deleted file mode 100644 index 8b3d6e3b1..000000000 Binary files a/lib/nusoap/docs/docs/media/images/function_folder.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/next_button.png b/lib/nusoap/docs/docs/media/images/next_button.png deleted file mode 100644 index cdbc615d9..000000000 Binary files a/lib/nusoap/docs/docs/media/images/next_button.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/next_button_disabled.png b/lib/nusoap/docs/docs/media/images/next_button_disabled.png deleted file mode 100644 index 4a11780fc..000000000 Binary files a/lib/nusoap/docs/docs/media/images/next_button_disabled.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/package.png b/lib/nusoap/docs/docs/media/images/package.png deleted file mode 100644 index b04cf566d..000000000 Binary files a/lib/nusoap/docs/docs/media/images/package.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/package_folder.png b/lib/nusoap/docs/docs/media/images/package_folder.png deleted file mode 100644 index 6162bafd9..000000000 Binary files a/lib/nusoap/docs/docs/media/images/package_folder.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/previous_button.png b/lib/nusoap/docs/docs/media/images/previous_button.png deleted file mode 100644 index 327fdbc23..000000000 Binary files a/lib/nusoap/docs/docs/media/images/previous_button.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/previous_button_disabled.png b/lib/nusoap/docs/docs/media/images/previous_button_disabled.png deleted file mode 100644 index c02ff64bf..000000000 Binary files a/lib/nusoap/docs/docs/media/images/previous_button_disabled.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/private_class_logo.png b/lib/nusoap/docs/docs/media/images/private_class_logo.png deleted file mode 100644 index 590e00640..000000000 Binary files a/lib/nusoap/docs/docs/media/images/private_class_logo.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/tutorial.png b/lib/nusoap/docs/docs/media/images/tutorial.png deleted file mode 100644 index bc1973752..000000000 Binary files a/lib/nusoap/docs/docs/media/images/tutorial.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/tutorial_folder.png b/lib/nusoap/docs/docs/media/images/tutorial_folder.png deleted file mode 100644 index 2a468b2a0..000000000 Binary files a/lib/nusoap/docs/docs/media/images/tutorial_folder.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/images/up_button.png b/lib/nusoap/docs/docs/media/images/up_button.png deleted file mode 100644 index ff36c5935..000000000 Binary files a/lib/nusoap/docs/docs/media/images/up_button.png and /dev/null differ diff --git a/lib/nusoap/docs/docs/media/stylesheet.css b/lib/nusoap/docs/docs/media/stylesheet.css deleted file mode 100644 index 77ce69643..000000000 --- a/lib/nusoap/docs/docs/media/stylesheet.css +++ /dev/null @@ -1,146 +0,0 @@ -a { color: #000090; text-decoration: none; } -a:hover, a:active, a:focus { color: highlighttext; background-color: highlight; text-decoration: none; } - -body { background: #FFFFFF; } -body, table { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt; } - -a img { border: 0px; } - -/* Page layout/boxes */ - -.info-box { } -.info-box-title { margin: 1em 0em 0em 0em; font-weight: normal; font-size: 14pt; color: #999999; border-bottom: 2px solid #999999; } -.info-box-body { border: 1px solid #999999; padding: .5em; } -.nav-bar { font-size: 8pt; white-space: nowrap; text-align: right; padding: .2em; margin: 0em 0em 1em 0em; } - -.oddrow { background-color: #F8F8F8; border: 1px solid #AAAAAA; padding: .5em; margin-bottom: 1em} -.evenrow { border: 1px solid #AAAAAA; padding: .5em; margin-bottom: 1em} - -.page-body { max-width: 800px; margin: auto; } -.tree { white-space: nowrap; font: icon } -.tree dd { margin-left: 19px } -.tree dl { margin: 0px } -.tree-icon { vertical-align: middle; border: 0px; margin-right: 3px } - -/* Index formatting classes */ - -.index-item-body { margin-top: .5em; margin-bottom: .5em} -.index-item-description { margin-top: .25em } -.index-item-details { font-weight: normal; font-style: italic; font-size: 8pt } -.index-letter-section { background-color: #EEEEEE; border: 1px dotted #999999; padding: .5em; margin-bottom: 1em} -.index-letter-title { font-size: 12pt; font-weight: bold } -.index-letter-menu { text-align: center; margin: 1em } -.index-letter { font-size: 12pt } - -/* Docbook classes */ - -.description {} -.short-description { font-weight: bold; color: #666666; } -.tags { padding-left: 0em; margin-left: 3em; color: #666666; list-style-type: square; } -.parameters { padding-left: 0em; margin-left: 3em; color: #014fbe; list-style-type: square; } -.redefinitions { font-size: 8pt; padding-left: 0em; margin-left: 2em; } -.package { font-weight: bold; } -.package-title { font-weight: bold; font-size: 14pt; border-bottom: 1px solid black } -.package-details { font-size: 85%; } -.sub-package { font-weight: bold; } -.tutorial { border-width: thin; border-color: #0066ff; } -.tutorial-nav-box { width: 100%; border: 1px solid #999999; background-color: #F8F8F8; } -.folder-title { font-style: italic; font-family: Verdana, Arial, Helvetica, sans-serif } - -/* Generic formatting */ - -.field { font-weight: bold; } -.detail { font-size: 8pt; } -.notes { font-style: italic; font-size: 8pt; } -.separator { background-color: #999999; height: 2px; } -.warning { color: #FF6600; } -.disabled { font-style: italic; color: #999999; } - -/* Code elements */ - -.line-number { } - -.class-table { width: 100%; } -.class-table-header { border-bottom: 1px dotted #666666; text-align: left} -.class-name { color: #0000AA; font-weight: bold; } - -.method-summary { color: #009000; padding-left: 1em; font-size: 8pt; } -.method-header { } -.method-definition { margin-bottom: .2em } -.method-title { color: #009000; font-weight: bold; } -.method-name { font-weight: bold; } -.method-signature { font-size: 85%; color: #666666; margin: .5em 0em } -.method-result { font-style: italic; } - -.var-summary { padding-left: 1em; font-size: 8pt; } -.var-header { } -.var-title { color: #014fbe; margin-bottom: .3em } -.var-type { font-style: italic; } -.var-name { font-weight: bold; } -.var-default {} -.var-description { font-weight: normal; color: #000000; } - -.include-title { color: #014fbe;} -.include-type { font-style: italic; } -.include-name { font-weight: bold; } - -.const-title { color: #FF6600; } -.const-name { font-weight: bold; } - -/* Syntax highlighting */ - -.src-code { } -*[class="src-code"] { line-height : 0.5em } - -.src-code a:link { padding: 1px; text-decoration: underline; color: #0000DD; } -.src-code a:visited { text-decoration: underline; color: #0000DD; } -.src-code a:active { background-color: #FFFF66; color: #008000; } -.src-code a:hover { background-color: #FFFF66; text-decoration: overline underline; color: #008000; } - -.src-comm { color: #666666; } -.src-id { color: #FF6600; font-style: italic; } -.src-inc { color: #0000AA; font-weight: bold; } -.src-key { color: #0000AA; font-weight: bold; } -.src-num { color: #CC0000; } -.src-str { color: #CC0000; } -.src-sym { } -.src-var { } - -.src-php { font-weight: bold; } - -.src-doc { color: #666666; } -.src-doc-close-template { color: #666666 } -.src-doc-coretag { color: #008000; } -.src-doc-inlinetag {} -.src-doc-internal {} -.src-doc-tag { color: #0080CC; } -.src-doc-template { color: #666666 } -.src-doc-type { font-style: italic; color: #444444 } -.src-doc-var { color: #444444 } - -.tute-tag { color: #009999 } -.tute-attribute-name { color: #0000FF } -.tute-attribute-value { color: #0099FF } -.tute-entity { font-weight: bold; } -.tute-comment { font-style: italic } -.tute-inline-tag { color: #636311; font-weight: bold } - -/* tutorial */ - -.authors { } -.author { font-style: italic; font-weight: bold } -.author-blurb { margin: .5em 0em .5em 2em; font-size: 85%; font-weight: normal; font-style: normal } -.example { border: 1px dashed #999999; background-color: #EEEEEE; padding: .5em; } -*[class="example"] { line-height : 0.5em; } -.listing { border: 1px dashed #999999; background-color: #EEEEEE; padding: .5em; white-space: nowrap; } -*[class="listing"] { line-height : 0.5em; } -.release-info { font-size: 85%; font-style: italic; margin: 1em 0em } -.ref-title-box { } -.ref-title { } -.ref-purpose { font-style: italic; color: #666666 } -.ref-synopsis { } -.title { font-weight: bold; border-bottom: 1px solid #999999; color: #999999; } -.cmd-synopsis { margin: 1em 0em } -.cmd-title { font-weight: bold } -.toc { margin-left: 2em; padding-left: 0em } - diff --git a/lib/nusoap/docs/docs/nusoap/CVS/Entries b/lib/nusoap/docs/docs/nusoap/CVS/Entries deleted file mode 100644 index a32b6e85b..000000000 --- a/lib/nusoap/docs/docs/nusoap/CVS/Entries +++ /dev/null @@ -1,15 +0,0 @@ -/XMLSchema.html/1.2/Mon Apr 26 19:25:21 2010// -/_class_wsdlcache_php.html/1.2/Mon Apr 26 19:16:49 2010// -/_nusoap_php.html/1.2/Mon Apr 26 19:17:09 2010// -/_nusoapmime_php.html/1.2/Mon Apr 26 19:17:11 2010// -/nusoap_base.html/1.2/Mon Apr 26 19:25:21 2010// -/soap_fault.html/1.2/Mon Apr 26 19:25:21 2010// -/soap_parser.html/1.2/Mon Apr 26 19:25:21 2010// -/soap_server.html/1.2/Mon Apr 26 19:25:21 2010// -/soap_transport_http.html/1.2/Mon Apr 26 19:25:21 2010// -/soapclient.html/1.2/Mon Apr 26 19:25:21 2010// -/soapclientmime.html/1.2/Mon Apr 26 19:25:21 2010// -/soapval.html/1.2/Mon Apr 26 19:25:21 2010// -/wsdl.html/1.2/Mon Apr 26 19:25:21 2010// -/wsdlcache.html/1.2/Mon Apr 26 19:25:21 2010// -D diff --git a/lib/nusoap/docs/docs/nusoap/CVS/Repository b/lib/nusoap/docs/docs/nusoap/CVS/Repository deleted file mode 100644 index 1b0feae91..000000000 --- a/lib/nusoap/docs/docs/nusoap/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -docs/nusoap diff --git a/lib/nusoap/docs/docs/nusoap/CVS/Root b/lib/nusoap/docs/docs/nusoap/CVS/Root deleted file mode 100644 index 38e068369..000000000 --- a/lib/nusoap/docs/docs/nusoap/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -:ext:snichol@nusoap.cvs.sourceforge.net:/cvsroot/nusoap diff --git a/lib/nusoap/docs/docs/nusoap/XMLSchema.html b/lib/nusoap/docs/docs/nusoap/XMLSchema.html deleted file mode 100644 index 53553b4b9..000000000 --- a/lib/nusoap/docs/docs/nusoap/XMLSchema.html +++ /dev/null @@ -1,331 +0,0 @@ - - - - - - Docs For Class XMLSchema - - - - -
    -

     Class XMLSchema

    - - -
    -
    Description
    - -
    - -

    Backward compatibility

    - -

    - Located in /nusoap.php (line 2048) -

    - - -
    nusoap_base
    -   |
    -   --nusoap_xmlschema
    -      |
    -      --XMLSchema
    - -
    -
    - - - - - - - - - -
    -
    Methods
    - -
    - -

    Inherited Methods

    - - -

    Inherited From nusoap_xmlschema

    -
    -  - nusoap_xmlschema::nusoap_xmlschema()
    -  - nusoap_xmlschema::addComplexType()
    -  - nusoap_xmlschema::addElement()
    -  - nusoap_xmlschema::addSimpleType()
    -  - nusoap_xmlschema::CreateTypeName()
    -  - nusoap_xmlschema::getPHPType()
    -  - nusoap_xmlschema::getTypeDef()
    -  - nusoap_xmlschema::parseFile()
    -  - nusoap_xmlschema::parseString()
    -  - nusoap_xmlschema::schemaCharacterData()
    -  - nusoap_xmlschema::schemaEndElement()
    -  - nusoap_xmlschema::schemaStartElement()
    -  - nusoap_xmlschema::serializeSchema()
    -  - nusoap_xmlschema::serializeTypeDef()
    -  - nusoap_xmlschema::typeToForm()
    -  - nusoap_xmlschema::xdebug()
    -
    - -

    Inherited From nusoap_base

    -
    -  - nusoap_base::nusoap_base()
    -  - nusoap_base::appendDebug()
    -  - nusoap_base::clearDebug()
    -  - nusoap_base::contractQname()
    -  - nusoap_base::debug()
    -  - nusoap_base::expandEntities()
    -  - nusoap_base::expandQname()
    -  - nusoap_base::formatDump()
    -  - nusoap_base::getDebug()
    -  - nusoap_base::getDebugAsXMLComment()
    -  - nusoap_base::getDebugLevel()
    -  - nusoap_base::getError()
    -  - nusoap_base::getGlobalDebugLevel()
    -  - nusoap_base::getLocalPart()
    -  - nusoap_base::getmicrotime()
    -  - nusoap_base::getNamespaceFromPrefix()
    -  - nusoap_base::getPrefix()
    -  - nusoap_base::getPrefixFromNamespace()
    -  - nusoap_base::isArraySimpleOrStruct()
    -  - nusoap_base::serializeEnvelope()
    -  - nusoap_base::serialize_val()
    -  - nusoap_base::setDebugLevel()
    -  - nusoap_base::setError()
    -  - nusoap_base::setGlobalDebugLevel()
    -  - nusoap_base::varDump()
    -  - nusoap_base::__toString()
    -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:08 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/_class_wsdlcache_php.html b/lib/nusoap/docs/docs/nusoap/_class_wsdlcache_php.html deleted file mode 100644 index 51c544e72..000000000 --- a/lib/nusoap/docs/docs/nusoap/_class_wsdlcache_php.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - Docs for page class.wsdlcache.php - - - - -
    -

    File/class.wsdlcache.php

    - - -
    -
    Description
    - -
    - - - -
    -
    - - -
    -
    Classes
    - -
    - - - - - - - - - - - - - -
    ClassDescription
    -  class - nusoap_wsdlcache - - caches instances of the wsdl class -
    -  class - wsdlcache - - For backward compatibility -
    -
    -
    - - - - - -

    - Documentation generated on Mon, 26 Apr 2010 16:16:48 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/_nusoap_php.html b/lib/nusoap/docs/docs/nusoap/_nusoap_php.html deleted file mode 100644 index d8e463594..000000000 --- a/lib/nusoap/docs/docs/nusoap/_nusoap_php.html +++ /dev/null @@ -1,315 +0,0 @@ - - - - - - Docs for page nusoap.php - - - - -
    -

    File/nusoap.php

    - - -
    -
    Description
    - -
    - - - -
    -
    - - -
    -
    Classes
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ClassDescription
    -  class - nusoap_base - - nusoap_base -
    -  class - nusoap_fault - - Contains information for a SOAP fault. -
    -  class - soap_fault - - Backward compatibility -
    -  class - nusoap_xmlschema - - parses an XML Schema, allows access to it's data, other utility methods. -
    -  class - XMLSchema - - Backward compatibility -
    -  class - soapval - - For creating serializable abstractions of native PHP types. This class -
    -  class - soap_transport_http - - transport class for sending/receiving data via HTTP and HTTPS NOTE: PHP must be compiled with the CURL extension for HTTPS support -
    -  class - nusoap_server - - nusoap_server allows the user to create a SOAP server that is capable of receiving messages and returning responses -
    -  class - soap_server - - Backward compatibility -
    -  class - wsdl - - parses a WSDL file, allows access to it's data, other utility methods. -
    -  class - nusoap_parser - - nusoap_parser class parses SOAP XML messages into native PHP values -
    -  class - soap_parser - - Backward compatibility -
    -  class - nusoap_client - - [nu]soapclient higher level class for easy usage. -
    -  class - soapclient - - For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded. -
    -
    -
    - - - - - -
    -
    Functions
    - -
    - -
    - -
    - - iso8601_to_timestamp (line 943) -
    - - -

    convert ISO 8601 compliant date string to unix timestamp

    -
      -
    • return: Unix timestamp (int) or false
    • -
    • access: public
    • -
    -
    - mixed - - iso8601_to_timestamp - - (string $datestr) -
    - -
      -
    • - string - $datestr: ISO 8601 compliant date string
    • -
    - - -
    - -
    - -
    - - timestamp_to_iso8601 (line 904) -
    - - -

    convert unix timestamp to ISO 8601 compliant date string

    -
      -
    • return: ISO 8601 date string or false
    • -
    • access: public
    • -
    -
    - mixed - - timestamp_to_iso8601 - - (int $timestamp, [boolean $utc = true]) -
    - -
      -
    • - int - $timestamp: Unix time stamp
    • -
    • - boolean - $utc: Whether the time stamp is UTC or local
    • -
    - - -
    - -
    - -
    - - usleepWindows (line 982) -
    - - -

    sleeps some number of microseconds

    -
      -
    • deprecated:
    • -
    • access: public
    • -
    -
    - void - - usleepWindows - - (string $usec) -
    - -
      -
    • - string - $usec: the number of microseconds to sleep
    • -
    - - -
    -
    -
    - -

    - Documentation generated on Mon, 26 Apr 2010 16:16:49 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/_nusoapmime_php.html b/lib/nusoap/docs/docs/nusoap/_nusoapmime_php.html deleted file mode 100644 index a9bd74165..000000000 --- a/lib/nusoap/docs/docs/nusoap/_nusoapmime_php.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - Docs for page nusoapmime.php - - - - -
    -

    File/nusoapmime.php

    - - -
    -
    Description
    - -
    - - - -
    -
    - - -
    -
    Classes
    - -
    - - - - - - - - - - - - - - - - - - - - - -
    ClassDescription
    -  class - nusoap_client_mime - - nusoap_client_mime client supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library. -
    -  class - soapclientmime - - nusoap_client_mime client supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library. -
    -  class - nusoap_server_mime - - nusoap_server_mime server supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library. -
    -  class - nusoapservermime - - nusoap_server_mime server supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library. -
    -
    -
    - - -
    -
    Includes
    - -
    - -
    - -
    -  - - require_once - ('Mail/mimeDecode.php') - (line 42) - -
    - - - -
    - -
    - -
    -  - - require_once - ('Mail/mimePart.php') - (line 43) - -
    - - - -
    -
    -
    - - - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:09 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/nusoap_base.html b/lib/nusoap/docs/docs/nusoap/nusoap_base.html deleted file mode 100644 index f32fcb2d6..000000000 --- a/lib/nusoap/docs/docs/nusoap/nusoap_base.html +++ /dev/null @@ -1,1577 +0,0 @@ - - - - - - Docs For Class nusoap_base - - - - -
    -

     Class nusoap_base

    - - -
    -
    Description
    - -
    - -

    nusoap_base

    - -

    - Located in /nusoap.php (line 85) -

    - - -
    
    -	
    -			
    -
    - - -
    -
    Direct descendents
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ClassDescription
    -  class - nusoap_fault - - Contains information for a SOAP fault. -
    -  class - nusoap_xmlschema - - parses an XML Schema, allows access to it's data, other utility methods. -
    -  class - soapval - - For creating serializable abstractions of native PHP types. This class -
    -  class - soap_transport_http - - transport class for sending/receiving data via HTTP and HTTPS NOTE: PHP must be compiled with the CURL extension for HTTPS support -
    -  class - nusoap_server - - nusoap_server allows the user to create a SOAP server that is capable of receiving messages and returning responses -
    -  class - wsdl - - parses a WSDL file, allows access to it's data, other utility methods. -
    -  class - nusoap_parser - - nusoap_parser class parses SOAP XML messages into native PHP values -
    -  class - nusoap_client - - [nu]soapclient higher level class for easy usage. -
    -
    -
    - - - -
    -
    Variable Summary
    - -
    -
    -
    -  - boolean - $charencoding -
    -
    -  - integer - $debugLevel -
    -
    -  - string - $debug_str -
    -
    -  - string - $error_str -
    -
    -  - array - $namespaces -
    -
    -  - string - $revision -
    -
    -  - string - $soap_defencoding -
    -
    -  - string - $title -
    -
    -  - array - $typemap -
    -
    -  - array - $usedNamespaces -
    -
    -  - string - $version -
    -
    -  - array - $xmlEntities -
    -
    -  - string - $XMLSchemaVersion -
    -
    -
    -
    - - -
    -
    Method Summary
    - -
    -
    - -
    -  - nusoap_base - nusoap_base - () -
    - -
    -  - void - appendDebug - (string $string) -
    - -
    -  - void - clearDebug - () -
    - -
    -  - string - contractQname - (string $qname) -
    - -
    -  - void - debug - (string $string) -
    - -
    -  - void - expandEntities - (string $val) -
    - -
    -  - string - expandQname - (string $qname) -
    - -
    -  - string - formatDump - (string $str) -
    - -
    -  - debug - &getDebug - () -
    - -
    -  - debug - &getDebugAsXMLComment - () -
    - -
    -  - int - getDebugLevel - () -
    - -
    -  - mixed - getError - () -
    - -
    -  - integer - getGlobalDebugLevel - () -
    - -
    -  - string - getLocalPart - (string $str) -
    - -
    -  - string - getmicrotime - () -
    - -
    -  - mixed - getNamespaceFromPrefix - (string $prefix) -
    - -
    -  - mixed - getPrefix - (string $str) -
    - -
    -  - mixed - getPrefixFromNamespace - (string $ns) -
    - -
    -  - string - isArraySimpleOrStruct - (mixed $val) -
    - -
    -  - string - serializeEnvelope - (string $body, [mixed $headers = false], [array $namespaces = array()], [string $style = 'rpc'], [string $use = 'encoded'], [string $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/']) -
    - -
    -  - string - serialize_val - (mixed $val, [string $name = false], [string $type = false], [string $name_ns = false], [string $type_ns = false], [array $attributes = false], [string $use = 'encoded'], [boolean $soapval = false]) -
    - -
    -  - void - setDebugLevel - (int $level) -
    - -
    -  - boolean - setError - (mixed $str) -
    - -
    -  - void - setGlobalDebugLevel - (int $level) -
    - -
    -  - string - varDump - (mixed $data) -
    - -
    -  - string - __toString - () -
    -
    -
    -
    - - -
    -
    Variables
    - -
    - -
    - -
    - - - boolean - $charencoding - = true (line 128) - -
    - - -

    toggles automatic encoding of special characters as entities (should always be true, I think)

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - integer - $debugLevel - (line 135) - -
    - - -

    the debug level for this instance

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - string - $debug_str - = '' (line 120) - -
    - - -

    Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - string - $error_str - = '' (line 113) - -
    - - -

    Current error string (manipulated by getError/setError)

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - array - $namespaces - = array(
    'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
    'xsd' => 'http://www.w3.org/2001/XMLSchema',
    'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
    'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
    )
    (line 162) -
    -
    - - -

    namespaces in an array of prefix => uri

    -

    this is "seeded" by a set of constants, but it may be altered by code

    -
      -
    • access: public
    • -
    - - - -
    -
    Redefined in descendants as:
    - - - -
    - -
    - -
    - - - string - $revision - = '$Revision: 1.2 $' (line 106) - -
    - - -

    CVS revision for HTTP headers.

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - string - $soap_defencoding - = 'ISO-8859-1' (line 151) - -
    - - -

    charset encoding for outgoing messages

    -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - string - $title - = 'NuSOAP' (line 92) - -
    - - -

    Identification for HTTP headers.

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - array - $typemap - = array(
    'http://www.w3.org/2001/XMLSchema' => array(
    'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
    'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
    'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
    // abstract "any" types
    'anyType'=>'string','anySimpleType'=>'string',
    // derived datatypes
    'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
    'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
    'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
    'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),'http://www.w3.org/2000/10/XMLSchema'=>array('i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double','float'=>'double','dateTime'=>'string','timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),'http://www.w3.org/1999/XMLSchema'=>array('i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double','float'=>'double','dateTime'=>'string','timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),'http://soapinterop.org/xsd'=>array('SOAPStruct'=>'struct'),'http://schemas.xmlsoap.org/soap/encoding/'=>array('base64'=>'string','array'=>'array','Array'=>'array'),'http://xml.apache.org/xml-soap'=>array('Map'))
    (line 184) -
    -
    - - -

    XML Schema types in an array of uri => (array of xml type => php type) is this legacy yet? no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.

    -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - array - $usedNamespaces - = array() (line 175) - -
    - - -

    namespaces used in the current context, e.g. during serialization

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - string - $version - = '0.9.5' (line 99) - -
    - - -

    Version for HTTP headers.

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - array - $xmlEntities - = array('quot' => '"','amp' => '&',
    'lt' => '<','gt' => '>','apos' => "'")
    (line 217) -
    -
    - - -

    XML entities to convert

    - - - - - - -
    - -
    - -
    - - - string - $XMLSchemaVersion - = 'http://www.w3.org/2001/XMLSchema' (line 143) - -
    - - -

    set schema version

    -
      -
    • access: public
    • -
    - - - - - -
    - -
    -
    - - -
    -
    Methods
    - -
    - - -
    - -
    - - Constructor nusoap_base (line 225) -
    - - -

    constructor

    -
      -
    • access: public
    • -
    - -
    - nusoap_base - - nusoap_base - - () -
    - - - -
    - -
    - -
    - - appendDebug (line 287) -
    - - -

    adds debug data to the instance debug string without formatting

    -
      -
    • access: public
    • -
    - -
    - void - - appendDebug - - (string $string) -
    - -
      -
    • - string - $string: debug data
    • -
    - - -
    - -
    - -
    - - clearDebug (line 300) -
    - - -

    clears the current debug data for this instance

    -
      -
    • access: public
    • -
    - -
    - void - - clearDebug - - () -
    - - - -
    - -
    - -
    - - contractQname (line 740) -
    - - -

    contracts (changes namespace to prefix) a qualified name

    -
      -
    • return: contracted qname
    • -
    • access: private
    • -
    - -
    - string - - contractQname - - (string $qname) -
    - -
      -
    • - string - $qname: qname
    • -
    - - -
    - -
    - -
    - - debug (line 275) -
    - - -

    adds debug data to the instance debug string with formatting

    -
      -
    • access: private
    • -
    - -
    - void - - debug - - (string $string) -
    - -
      -
    • - string - $string: debug data
    • -
    - - -
    - -
    - -
    - - expandEntities (line 341) -
    - - -

    expands entities, e.g. changes '<' to '&lt;'.

    -
      -
    • access: private
    • -
    - -
    - void - - expandEntities - - (string $val) -
    - -
      -
    • - string - $val: The string in which to expand entities.
    • -
    - - -
    - -
    - -
    - - expandQname (line 765) -
    - - -

    expands (changes prefix to namespace) a qualified name

    -
      -
    • return: expanded qname
    • -
    • access: private
    • -
    - -
    - string - - expandQname - - (string $qname) -
    - -
      -
    • - string - $qname: qname
    • -
    - - -
    - -
    - -
    - - formatDump (line 728) -
    - - -

    formats a string to be inserted into an HTML stream

    -
      -
    • return: The formatted string
    • -
    • deprecated:
    • -
    • access: public
    • -
    - -
    - string - - formatDump - - (string $str) -
    - -
      -
    • - string - $str: The string to format
    • -
    - - -
    - -
    - -
    - - getDebug (line 312) -
    - - -

    gets the current debug data for this instance

    -
      -
    • return: data
    • -
    • access: public
    • -
    - -
    - debug - - &getDebug - - () -
    - - - -
    - -
    - -
    - - getDebugAsXMLComment (line 325) -
    - - -

    gets the current debug data for this instance as an XML comment this may change the contents of the debug data

    -
      -
    • return: data as an XML comment
    • -
    • access: public
    • -
    - -
    - debug - - &getDebugAsXMLComment - - () -
    - - - -
    - -
    - -
    - - getDebugLevel (line 255) -
    - - -

    gets the debug level for this instance

    -
      -
    • return: Debug level 0-9, where 0 turns off
    • -
    • access: public
    • -
    - -
    - int - - getDebugLevel - - () -
    - - - -
    - -
    - -
    - - getError (line 358) -
    - - -

    returns error string if present

    -
      -
    • return: error string or false
    • -
    • access: public
    • -
    - -
    - mixed - - getError - - () -
    - - - -
    - -
    - -
    - - getGlobalDebugLevel (line 235) -
    - - -

    gets the global debug level, which applies to future instances

    -
      -
    • return: Debug level 0-9, where 0 turns off
    • -
    • access: public
    • -
    - -
    - integer - - getGlobalDebugLevel - - () -
    - - - -
    - -
    - -
    - - getLocalPart (line 790) -
    - - -

    returns the local part of a prefixed string returns the original string, if not prefixed

    -
      -
    • return: The local part
    • -
    • access: public
    • -
    - -
    - string - - getLocalPart - - (string $str) -
    - -
      -
    • - string - $str: The prefixed string
    • -
    - - -
    - -
    - -
    - - getmicrotime (line 854) -
    - - -

    returns the time in ODBC canonical form with microseconds

    -
      -
    • return: The time in ODBC canonical form with microseconds
    • -
    • access: public
    • -
    - -
    - string - - getmicrotime - - () -
    - - - -
    - -
    - -
    - - getNamespaceFromPrefix (line 822) -
    - - -

    pass it a prefix, it returns a namespace

    -
      -
    • return: The namespace, false if no namespace has the specified prefix
    • -
    • access: public
    • -
    - -
    - mixed - - getNamespaceFromPrefix - - (string $prefix) -
    - -
      -
    • - string - $prefix: The prefix
    • -
    - - -
    - -
    - -
    - - getPrefix (line 807) -
    - - -

    returns the prefix part of a prefixed string returns false, if not prefixed

    -
      -
    • return: The prefix or false if there is no prefix
    • -
    • access: public
    • -
    - -
    - mixed - - getPrefix - - (string $str) -
    - -
      -
    • - string - $str: The prefixed string
    • -
    - - -
    - -
    - -
    - - getPrefixFromNamespace (line 838) -
    - - -

    returns the prefix for a given namespace (or prefix) or false if no prefixes registered for the given namespace

    -
      -
    • return: The prefix, false if the namespace has no prefixes
    • -
    • access: public
    • -
    - -
    - mixed - - getPrefixFromNamespace - - (string $ns) -
    - -
      -
    • - string - $ns: The namespace
    • -
    - - -
    - -
    - -
    - - isArraySimpleOrStruct (line 382) -
    - - -

    detect if array is a simple array or a struct (associative array)

    -
      -
    • return: (arraySimple|arrayStruct)
    • -
    • access: private
    • -
    - -
    - string - - isArraySimpleOrStruct - - (mixed $val) -
    - -
      -
    • - mixed - $val: The PHP array
    • -
    - - -
    - -
    - -
    - - serializeEnvelope (line 673) -
    - - -

    serializes a message

    -
      -
    • return: the message
    • -
    • access: public
    • -
    - -
    - string - - serializeEnvelope - - (string $body, [mixed $headers = false], [array $namespaces = array()], [string $style = 'rpc'], [string $use = 'encoded'], [string $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/']) -
    - -
      -
    • - string - $body: the XML of the SOAP body
    • -
    • - mixed - $headers: optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
    • -
    • - array - $namespaces: optional the namespaces used in generating the body and headers
    • -
    • - string - $style: optional (rpc|document)
    • -
    • - string - $use: optional (encoded|literal)
    • -
    • - string - $encodingStyle: optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
    • -
    - - -
    - -
    - -
    - - serialize_val (line 407) -
    - - -

    serializes PHP values in accordance w/ section 5. Type information is not serialized if $use == 'literal'.

    -
      -
    • return: The serialized element, possibly with child elements
    • -
    • access: public
    • -
    - -
    - string - - serialize_val - - (mixed $val, [string $name = false], [string $type = false], [string $name_ns = false], [string $type_ns = false], [array $attributes = false], [string $use = 'encoded'], [boolean $soapval = false]) -
    - -
      -
    • - mixed - $val: The value to serialize
    • -
    • - string - $name: The name (local part) of the XML element
    • -
    • - string - $type: The XML schema type (local part) for the element
    • -
    • - string - $name_ns: The namespace for the name of the XML element
    • -
    • - string - $type_ns: The namespace for the type of the element
    • -
    • - array - $attributes: The attributes to serialize as name=>value pairs
    • -
    • - string - $use: The WSDL "use" (encoded|literal)
    • -
    • - boolean - $soapval: Whether this is called from soapval.
    • -
    - - -
    - -
    - -
    - - setDebugLevel (line 265) -
    - - -

    sets the debug level for this instance

    -
      -
    • access: public
    • -
    - -
    - void - - setDebugLevel - - (int $level) -
    - -
      -
    • - int - $level: Debug level 0-9, where 0 turns off
    • -
    - - -
    - -
    - -
    - - setError (line 371) -
    - - -

    sets error string

    -
      -
    • return: error string
    • -
    • access: private
    • -
    - -
    - boolean - - setError - - (mixed $str) -
    - - - -
    - -
    - -
    - - setGlobalDebugLevel (line 245) -
    - - -

    sets the global debug level, which applies to future instances

    -
      -
    • access: public
    • -
    - -
    - void - - setGlobalDebugLevel - - (int $level) -
    - -
      -
    • - int - $level: Debug level 0-9, where 0 turns off
    • -
    - - -
    - -
    - -
    - - varDump (line 873) -
    - - -

    Returns a string with the output of var_dump

    -
      -
    • return: The output of var_dump
    • -
    • access: public
    • -
    - -
    - string - - varDump - - (mixed $data) -
    - -
      -
    • - mixed - $data: The variable to var_dump
    • -
    - - -
    - -
    - -
    - - __toString (line 887) -
    - - -

    represents the object as a string

    -
      -
    • access: public
    • -
    - -
    - string - - __toString - - () -
    - - - -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:01 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/nusoap_client.html b/lib/nusoap/docs/docs/nusoap/nusoap_client.html deleted file mode 100644 index 3cd176e0e..000000000 --- a/lib/nusoap/docs/docs/nusoap/nusoap_client.html +++ /dev/null @@ -1,2304 +0,0 @@ - - - - - - Docs For Class nusoap_client - - - - -
    -

     Class nusoap_client

    - - -
    -
    Description
    - -
    - -

    [nu]soapclient higher level class for easy usage.

    -

    usage:

    // instantiate client with server info $soapclient = new nusoap_client( string path [ ,mixed wsdl] );

    // call method, get results echo $soapclient->call( string methodname [ ,array parameters] );

    // bye bye client unset($soapclient);

    - -

    - Located in /nusoap.php (line 7097) -

    - - -
    nusoap_base
    -   |
    -   --nusoap_client
    - -
    -
    - - -
    -
    Direct descendents
    - -
    - - - - - - - - - - - - - -
    ClassDescription
    -  class - soapclient - - For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded. -
    -  class - nusoap_client_mime - - nusoap_client_mime client supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library. -
    -
    -
    - - - -
    -
    Variable Summary
    - -
    -
    -
    -  - mixed - $authtype -
    -
    -  - mixed - $bindingType -
    -
    -  - mixed - $certRequest -
    -
    -  - mixed - $cookies -
    -
    -  - mixed - $curl_options -
    -
    -  - mixed - $decode_utf8 -
    -
    -  - mixed - $defaultRpcParams -
    -
    -  - mixed - $document -
    -
    -  - mixed - $endpoint -
    -
    -  - mixed - $endpointType -
    -
    -  - fault - $fault -
    -
    -  - faultcode - $faultcode -
    -
    -  - faultdetail - $faultdetail -
    -
    -  - faultstring - $faultstring -
    -
    -  - mixed - $forceEndpoint -
    -
    -  - mixed - $http_encoding -
    -
    -  - mixed - $operations -
    -
    -  - mixed - $password -
    -
    -  - mixed - $persistentConnection -
    -
    -  - mixed - $portName -
    -
    -  - mixed - $proxyhost -
    -
    -  - mixed - $proxypassword -
    -
    -  - mixed - $proxyport -
    -
    -  - mixed - $proxyusername -
    -
    -  - mixed - $request -
    -
    -  - mixed - $requestHeaders -
    -
    -  - mixed - $response -
    -
    -  - mixed - $responseData -
    -
    -  - mixed - $responseHeader -
    -
    -  - mixed - $responseHeaders -
    -
    -  - mixed - $response_timeout -
    -
    -  - mixed - $timeout -
    -
    -  - mixed - $username -
    -
    -  - mixed - $use_curl -
    -
    -  - mixed - $xml_encoding -
    -
    -
    -
    - - -
    -
    Method Summary
    - -
    -
    - -
    -  - nusoap_client - nusoap_client - (mixed $endpoint, [mixed $wsdl = false], [string $proxyhost = false], [string $proxyport = false], [string $proxyusername = false], [string $proxypassword = false], integer $timeout, [integer $response_timeout = 30], [string $portName = '']) -
    - -
    -  - mixed - call - (string $operation, [mixed $params = array()], [string $namespace = 'http://tempuri.org'], [string $soapAction = ''], [mixed $headers = false], [boolean $rpcParams = null], [string $style = 'rpc'], [string $use = 'encoded']) -
    - -
    -  - boolean - checkCookies - () -
    - -
    -  - void - checkWSDL - () -
    - -
    -  - void - decodeUTF8 - (mixed $bool) -
    - -
    -  - array - getCookies - () -
    - -
    -  - boolean - getDefaultRpcParams - () -
    - -
    -  - mixed - getHeader - () -
    - -
    -  - string - getHeaders - () -
    - -
    -  - string - getHTTPBody - (string $soapmsg) -
    - -
    -  - string - getHTTPContentType - () -
    - -
    -  - string - getHTTPContentTypeCharset - () -
    - -
    -  - array - getOperationData - (string $operation) -
    - -
    -  - object soap_proxy - getProxy - () -
    - -
    -  - string - getProxyClassCode - () -
    - -
    -  - void - loadWSDL - () -
    - -
    -  - mixed - parseResponse - (array $headers, string $data) -
    - -
    -  - mixed - send - (string $msg, [string $soapaction = ''], integer $timeout, [integer $response_timeout = 30]) -
    - -
    -  - boolean - setCookie - (string $name, string $value) -
    - -
    -  - void - setCredentials - (string $username, string $password, [string $authtype = 'basic'], [array $certRequest = array()]) -
    - -
    -  - void - setCurlOption - (mixed $option, mixed $value) -
    - -
    -  - void - setDefaultRpcParams - (boolean $rpcParams) -
    - -
    -  - void - setEndpoint - (string $endpoint) -
    - -
    -  - void - setHeaders - (mixed $headers) -
    - -
    -  - void - setHTTPEncoding - ([string $enc = 'gzip, deflate']) -
    - -
    -  - void - setHTTPProxy - (string $proxyhost, string $proxyport, [string $proxyusername = ''], [string $proxypassword = '']) -
    - -
    -  - void - setUseCURL - (boolean $use) -
    - -
    -  - boolean - UpdateCookies - (array $cookies) -
    - -
    -  - void - useHTTPPersistentConnection - () -
    - -
    -  - string - _getProxyClassCode - (mixed $r) -
    -
    -
    -
    - - -
    -
    Variables
    - -
    - -
    - -
    - - - mixed - $authtype - = '' (line 7101) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $bindingType - = '' (line 7128) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $certRequest - = array() (line 7102) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $cookies - = array() (line 7124) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $curl_options - = array() (line 7127) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $decode_utf8 - = true (line 7125) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $defaultRpcParams - = false (line 7120) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $document - = '' (line 7106) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $endpoint - (line 7107) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $endpointType - = '' (line 7118) - -
    - - - - - - - -
    - -
    - -
    - - - fault - $fault - (line 7138) - -
    - - -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - faultcode - $faultcode - (line 7143) - -
    - - -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - faultdetail - $faultdetail - (line 7153) - -
    - - -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - faultstring - $faultstring - (line 7148) - -
    - - -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - mixed - $forceEndpoint - = '' (line 7108) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $http_encoding - = false (line 7115) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $operations - = array() (line 7126) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $password - = '' (line 7100) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $persistentConnection - = false (line 7119) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $portName - = '' (line 7113) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $proxyhost - = '' (line 7109) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $proxypassword - = '' (line 7112) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $proxyport - = '' (line 7110) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $proxyusername - = '' (line 7111) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $request - = '' (line 7121) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $requestHeaders - = false (line 7103) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $response - = '' (line 7122) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $responseData - = '' (line 7123) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $responseHeader - = NULL (line 7105) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $responseHeaders - = '' (line 7104) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $response_timeout - = 30 (line 7117) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $timeout - = 0 (line 7116) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $username - = '' (line 7099) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $use_curl - = false (line 7129) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $xml_encoding - = '' (line 7114) - -
    - - - - - - - -
    -

    Inherited Variables

    - -

    Inherited from nusoap_base

    -
    - - - nusoap_base::$charencoding
    -
    - - - nusoap_base::$debugLevel
    -
    - - - nusoap_base::$debug_str
    -
    - - - nusoap_base::$error_str
    -
    - - - nusoap_base::$namespaces
    -
    - - - nusoap_base::$revision
    -
    - - - nusoap_base::$soap_defencoding
    -
    - - - nusoap_base::$title
    -
    - - - nusoap_base::$typemap
    -
    - - - nusoap_base::$usedNamespaces
    -
    - - - nusoap_base::$version
    -
    - - - nusoap_base::$xmlEntities
    -
    - - - nusoap_base::$XMLSchemaVersion
    -
    -
    - -
    -
    - - -
    -
    Methods
    - -
    - - -
    - -
    - - Constructor nusoap_client (line 7169) -
    - - -

    constructor

    -
      -
    • access: public
    • -
    - -
    - nusoap_client - - nusoap_client - - (mixed $endpoint, [mixed $wsdl = false], [string $proxyhost = false], [string $proxyport = false], [string $proxyusername = false], [string $proxypassword = false], integer $timeout, [integer $response_timeout = 30], [string $portName = '']) -
    - -
      -
    • - mixed - $endpoint: SOAP server or WSDL URL (string), or wsdl instance (object)
    • -
    • - mixed - $wsdl: optional, set to 'wsdl' or true if using WSDL
    • -
    • - string - $proxyhost: optional
    • -
    • - string - $proxyport: optional
    • -
    • - string - $proxyusername: optional
    • -
    • - string - $proxypassword: optional
    • -
    • - integer - $timeout: set the connection timeout
    • -
    • - integer - $response_timeout: set the response timeout
    • -
    • - string - $portName: optional portName in WSDL document
    • -
    - - -
    - -
    - -
    - - call (line 7228) -
    - - -

    calls method, returns PHP native type

    -
      -
    • return: response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors
    • -
    • access: public
    • -
    - -
    - mixed - - call - - (string $operation, [mixed $params = array()], [string $namespace = 'http://tempuri.org'], [string $soapAction = ''], [mixed $headers = false], [boolean $rpcParams = null], [string $style = 'rpc'], [string $use = 'encoded']) -
    - -
      -
    • - string - $operation: SOAP server URL or path
    • -
    • - mixed - $params: An array, associative or simple, of the parameters for the method call, or a string that is the XML for the call. For rpc style, this call will wrap the XML in a tag named after the method, as well as the SOAP Envelope and Body. For document style, this will only wrap with the Envelope and Body. IMPORTANT: when using an array with document style, in which case there is really one parameter, the root of the fragment used in the call, which encloses what programmers normally think of parameters. A parameter array *must* include the wrapper.
    • -
    • - string - $namespace: optional method namespace (WSDL can override)
    • -
    • - string - $soapAction: optional SOAPAction value (WSDL can override)
    • -
    • - mixed - $headers: optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
    • -
    • - boolean - $rpcParams: optional (no longer used)
    • -
    • - string - $style: optional (rpc|document) the style to use when serializing parameters (WSDL can override)
    • -
    • - string - $use: optional (encoded|literal) the use when serializing parameters (WSDL can override)
    • -
    - - -
    - -
    - -
    - - checkCookies (line 7959) -
    - - -

    checks all Cookies and delete those which are expired

    -
      -
    • return: always return true
    • -
    • access: private
    • -
    - -
    - boolean - - checkCookies - - () -
    - - - -
    - -
    - -
    - - checkWSDL (line 7410) -
    - - -

    check WSDL passed as an instance or pulled from an endpoint

    -
      -
    • access: private
    • -
    - -
    - void - - checkWSDL - - () -
    - - - -
    - -
    - -
    - - decodeUTF8 (line 7922) -
    - - - -
    - void - - decodeUTF8 - - (mixed $bool) -
    - - - -
    - -
    - -
    - - getCookies (line 7949) -
    - - -

    gets all Cookies

    -
      -
    • return: with all internal cookies
    • -
    • access: public
    • -
    - -
    - array - - getCookies - - () -
    - - - -
    - -
    - -
    - - getDefaultRpcParams (line 7746) -
    - - -

    gets the default RPC parameter setting.

    -

    If true, default is that call params are like RPC even for document style. Each call() can override this value.

    This is no longer used.

    -
      -
    • deprecated:
    • -
    • access: public
    • -
    - -
    - boolean - - getDefaultRpcParams - - () -
    - - - -
    - -
    - -
    - - getHeader (line 7665) -
    - - -

    get the SOAP response Header (parsed)

    -
      -
    • access: public
    • -
    - -
    - mixed - - getHeader - - () -
    - - - -
    - -
    - -
    - - getHeaders (line 7655) -
    - - -

    get the SOAP response headers (namespace resolution incomplete)

    -
      -
    • access: public
    • -
    - -
    - string - - getHeaders - - () -
    - - - -
    - -
    - -
    - - getHTTPBody (line 7887) -
    - - -

    gets the HTTP body for the current request.

    -
      -
    • return: The HTTP body, which includes the SOAP payload
    • -
    • access: private
    • -
    - -
    - string - - getHTTPBody - - (string $soapmsg) -
    - -
      -
    • - string - $soapmsg: The SOAP payload
    • -
    - - -
    -
    Redefined in descendants as:
    - -
    - -
    - -
    - - getHTTPContentType (line 7899) -
    - - -

    gets the HTTP content type for the current request.

    -

    Note: getHTTPBody must be called before this.

    -
      -
    • return: the HTTP content type for the current request.
    • -
    • access: private
    • -
    - -
    - string - - getHTTPContentType - - () -
    - - - -
    -
    Redefined in descendants as:
    - -
    - -
    - -
    - - getHTTPContentTypeCharset (line 7912) -
    - - -

    gets the HTTP content type charset for the current request.

    -

    returns false for non-text content types.

    Note: getHTTPBody must be called before this.

    -
      -
    • return: the HTTP content type charset for the current request.
    • -
    • access: private
    • -
    - -
    - string - - getHTTPContentTypeCharset - - () -
    - - - -
    -
    Redefined in descendants as:
    - -
    - -
    - -
    - - getOperationData (line 7459) -
    - - -

    get available data pertaining to an operation

    -
      -
    • return: array of data pertaining to the operation
    • -
    • access: public
    • -
    - -
    - array - - getOperationData - - (string $operation) -
    - -
      -
    • - string - $operation: operation name
    • -
    - - -
    - -
    - -
    - - getProxy (line 7772) -
    - - -

    dynamically creates an instance of a proxy class, allowing user to directly call methods from wsdl

    -
      -
    • return: object
    • -
    • access: public
    • -
    - -
    - object soap_proxy - - getProxy - - () -
    - - - -
    - -
    - -
    - - getProxyClassCode (line 7875) -
    - - -

    dynamically creates proxy class code

    -
      -
    • return: PHP/NuSOAP code for the proxy class
    • -
    • access: public
    • -
    - -
    - string - - getProxyClassCode - - () -
    - - - -
    - -
    - -
    - - loadWSDL (line 7444) -
    - - -

    instantiate wsdl object and parse wsdl file

    -
      -
    • access: public
    • -
    - -
    - void - - loadWSDL - - () -
    - - - -
    - -
    - -
    - - parseResponse (line 7564) -
    - - -

    processes SOAP message returned from server

    -
      -
    • return: value of the message, decoded into a PHP type
    • -
    • access: private
    • -
    - -
    - mixed - - parseResponse - - (array $headers, string $data) -
    - -
      -
    • - array - $headers: The HTTP headers
    • -
    • - string - $data: unprocessed response data from server
    • -
    - - -
    -
    Redefined in descendants as:
    - -
    - -
    - -
    - - send (line 7485) -
    - - -

    send the SOAP message

    -

    Note: if the operation has multiple return values the return value of this method will be an array of those values.

    -
      -
    • return: native PHP types.
    • -
    • access: private
    • -
    - -
    - mixed - - send - - (string $msg, [string $soapaction = ''], integer $timeout, [integer $response_timeout = 30]) -
    - -
      -
    • - string - $msg: a SOAPx4 soapmsg object
    • -
    • - string - $soapaction: SOAPAction value
    • -
    • - integer - $timeout: set connection timeout in seconds
    • -
    • - integer - $response_timeout: set response timeout in seconds
    • -
    - - -
    - -
    - -
    - - setCookie (line 7935) -
    - - -

    adds a new Cookie into $this->cookies array

    -
      -
    • return: if cookie-set was successful returns true, else false
    • -
    • access: public
    • -
    - -
    - boolean - - setCookie - - (string $name, string $value) -
    - -
      -
    • - string - $name: Cookie Name
    • -
    • - string - $value: Cookie Value
    • -
    - - -
    - -
    - -
    - - setCredentials (line 7694) -
    - - -

    if authenticating, set user credentials here

    -
      -
    • access: public
    • -
    - -
    - void - - setCredentials - - (string $username, string $password, [string $authtype = 'basic'], [array $certRequest = array()]) -
    - -
      -
    • - string - $username
    • -
    • - string - $password
    • -
    • - string - $authtype: (basic|digest|certificate|ntlm)
    • -
    • - array - $certRequest: (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
    • -
    - - -
    - -
    - -
    - - setCurlOption (line 7620) -
    - - -

    sets user-specified cURL options

    -
      -
    • access: public
    • -
    - -
    - void - - setCurlOption - - (mixed $option, mixed $value) -
    - -
      -
    • - mixed - $option: The cURL option (always integer?)
    • -
    • - mixed - $value: The cURL option value
    • -
    - - -
    - -
    - -
    - - setDefaultRpcParams (line 7761) -
    - - -

    sets the default RPC parameter setting.

    -

    If true, default is that call params are like RPC even for document style Each call() can override this value.

    This is no longer used.

    -
      -
    • deprecated:
    • -
    • access: public
    • -
    - -
    - void - - setDefaultRpcParams - - (boolean $rpcParams) -
    - -
      -
    • - boolean - $rpcParams
    • -
    - - -
    - -
    - -
    - - setEndpoint (line 7632) -
    - - -

    sets the SOAP endpoint, which can override WSDL

    -
      -
    • access: public
    • -
    - -
    - void - - setEndpoint - - (string $endpoint) -
    - -
      -
    • - string - $endpoint: The endpoint URL to use, or empty string or false to prevent override
    • -
    - - -
    - -
    - -
    - - setHeaders (line 7643) -
    - - -

    set the SOAP headers

    -
      -
    • access: public
    • -
    - -
    - void - - setHeaders - - (mixed $headers) -
    - -
      -
    • - mixed - $headers: String of XML with SOAP header content, or array of soapval objects for SOAP headers
    • -
    - - -
    - -
    - -
    - - setHTTPEncoding (line 7709) -
    - - -

    use HTTP encoding

    -
      -
    • access: public
    • -
    - -
    - void - - setHTTPEncoding - - ([string $enc = 'gzip, deflate']) -
    - -
      -
    • - string - $enc: HTTP encoding
    • -
    - - -
    - -
    - -
    - - setHTTPProxy (line 7678) -
    - - -

    set proxy info here

    -
      -
    • access: public
    • -
    - -
    - void - - setHTTPProxy - - (string $proxyhost, string $proxyport, [string $proxyusername = ''], [string $proxypassword = '']) -
    - -
      -
    • - string - $proxyhost
    • -
    • - string - $proxyport
    • -
    • - string - $proxyusername
    • -
    • - string - $proxypassword
    • -
    - - -
    - -
    - -
    - - setUseCURL (line 7720) -
    - - -

    Set whether to try to use cURL connections if possible

    -
      -
    • access: public
    • -
    - -
    - void - - setUseCURL - - (boolean $use) -
    - -
      -
    • - boolean - $use: Whether to try to use cURL
    • -
    - - -
    - -
    - -
    - - UpdateCookies (line 7992) -
    - - -

    updates the current cookies with a new set

    -
      -
    • return: always return true
    • -
    • access: private
    • -
    - -
    - boolean - - UpdateCookies - - (array $cookies) -
    - -
      -
    • - array - $cookies: new cookies with which to update current ones
    • -
    - - -
    - -
    - -
    - - useHTTPPersistentConnection (line 7730) -
    - - -

    use HTTP persistent connections if possible

    -
      -
    • access: public
    • -
    - -
    - void - - useHTTPPersistentConnection - - () -
    - - - -
    - -
    - -
    - - _getProxyClassCode (line 7820) -
    - - -

    dynamically creates proxy class code

    -
      -
    • return: PHP/NuSOAP code for the proxy class
    • -
    • access: private
    • -
    - -
    - string - - _getProxyClassCode - - (mixed $r) -
    - - - -
    -

    Inherited Methods

    - - -

    Inherited From nusoap_base

    -
    -  - nusoap_base::nusoap_base()
    -  - nusoap_base::appendDebug()
    -  - nusoap_base::clearDebug()
    -  - nusoap_base::contractQname()
    -  - nusoap_base::debug()
    -  - nusoap_base::expandEntities()
    -  - nusoap_base::expandQname()
    -  - nusoap_base::formatDump()
    -  - nusoap_base::getDebug()
    -  - nusoap_base::getDebugAsXMLComment()
    -  - nusoap_base::getDebugLevel()
    -  - nusoap_base::getError()
    -  - nusoap_base::getGlobalDebugLevel()
    -  - nusoap_base::getLocalPart()
    -  - nusoap_base::getmicrotime()
    -  - nusoap_base::getNamespaceFromPrefix()
    -  - nusoap_base::getPrefix()
    -  - nusoap_base::getPrefixFromNamespace()
    -  - nusoap_base::isArraySimpleOrStruct()
    -  - nusoap_base::serializeEnvelope()
    -  - nusoap_base::serialize_val()
    -  - nusoap_base::setDebugLevel()
    -  - nusoap_base::setError()
    -  - nusoap_base::setGlobalDebugLevel()
    -  - nusoap_base::varDump()
    -  - nusoap_base::__toString()
    -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:02 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/nusoap_client_mime.html b/lib/nusoap/docs/docs/nusoap/nusoap_client_mime.html deleted file mode 100644 index ba9ca88ba..000000000 --- a/lib/nusoap/docs/docs/nusoap/nusoap_client_mime.html +++ /dev/null @@ -1,846 +0,0 @@ - - - - - - Docs For Class nusoap_client_mime - - - - -
    -

     Class nusoap_client_mime

    - - -
    -
    Description
    - -
    - -

    nusoap_client_mime client supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.

    -
      -
    • access: public
    • -
    • version: $Id: nusoapmime.php,v 1.13 2010/04/26 20:15:08 snichol Exp $
    • -
    • author: Scott Nichol <snichol@users.sourceforge.net>
    • -
    • author: Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
    • -
    -

    - Located in /nusoapmime.php (line 54) -

    - - -
    nusoap_base
    -   |
    -   --nusoap_client
    -      |
    -      --nusoap_client_mime
    - -
    -
    - - -
    -
    Direct descendents
    - -
    - - - - - - - - - -
    ClassDescription
    -  class - soapclientmime - - nusoap_client_mime client supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library. -
    -
    -
    - - - -
    -
    Variable Summary
    - -
    -
    -
    -  - string - $mimeContentType -
    -
    -  - array - $requestAttachments -
    -
    -  - array - $responseAttachments -
    -
    -
    -
    - - -
    -
    Method Summary
    - -
    -
    - -
    -  - string - addAttachment - (string $data, [string $filename = ''], [string $contenttype = 'application/octet-stream'], [string $cid = false]) -
    - -
    -  - void - clearAttachments - () -
    - -
    -  - array - getAttachments - () -
    - -
    -  - string - getHTTPBody - (string $soapmsg) -
    - -
    -  - string - getHTTPContentType - () -
    - -
    -  - string - getHTTPContentTypeCharset - () -
    - -
    -  - mixed - parseResponse - (array $headers, string $data) -
    -
    -
    -
    - - -
    -
    Variables
    - -
    - -
    - -
    - - - string - $mimeContentType - (line 71) - -
    - - -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - array - $requestAttachments - = array() (line 60) - -
    - - -
      -
    • var: Each array element in the return is an associative array with keys data, filename, contenttype, cid
    • -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - array - $responseAttachments - (line 66) - -
    - - -
      -
    • var: Each array element in the return is an associative array with keys data, filename, contenttype, cid
    • -
    • access: private
    • -
    - - - - - -
    -

    Inherited Variables

    - -

    Inherited from nusoap_client

    -
    - - - nusoap_client::$authtype
    -
    - - - nusoap_client::$bindingType
    -
    - - - nusoap_client::$certRequest
    -
    - - - nusoap_client::$cookies
    -
    - - - nusoap_client::$curl_options
    -
    - - - nusoap_client::$decode_utf8
    -
    - - - nusoap_client::$defaultRpcParams
    -
    - - - nusoap_client::$document
    -
    - - - nusoap_client::$endpoint
    -
    - - - nusoap_client::$endpointType
    -
    - - - nusoap_client::$fault
    -
    - - - nusoap_client::$faultcode
    -
    - - - nusoap_client::$faultdetail
    -
    - - - nusoap_client::$faultstring
    -
    - - - nusoap_client::$forceEndpoint
    -
    - - - nusoap_client::$http_encoding
    -
    - - - nusoap_client::$operations
    -
    - - - nusoap_client::$password
    -
    - - - nusoap_client::$persistentConnection
    -
    - - - nusoap_client::$portName
    -
    - - - nusoap_client::$proxyhost
    -
    - - - nusoap_client::$proxypassword
    -
    - - - nusoap_client::$proxyport
    -
    - - - nusoap_client::$proxyusername
    -
    - - - nusoap_client::$request
    -
    - - - nusoap_client::$requestHeaders
    -
    - - - nusoap_client::$response
    -
    - - - nusoap_client::$responseData
    -
    - - - nusoap_client::$responseHeader
    -
    - - - nusoap_client::$responseHeaders
    -
    - - - nusoap_client::$response_timeout
    -
    - - - nusoap_client::$timeout
    -
    - - - nusoap_client::$username
    -
    - - - nusoap_client::$use_curl
    -
    - - - nusoap_client::$xml_encoding
    -
    -
    -

    Inherited from nusoap_base

    -
    - - - nusoap_base::$charencoding
    -
    - - - nusoap_base::$debugLevel
    -
    - - - nusoap_base::$debug_str
    -
    - - - nusoap_base::$error_str
    -
    - - - nusoap_base::$namespaces
    -
    - - - nusoap_base::$revision
    -
    - - - nusoap_base::$soap_defencoding
    -
    - - - nusoap_base::$title
    -
    - - - nusoap_base::$typemap
    -
    - - - nusoap_base::$usedNamespaces
    -
    - - - nusoap_base::$version
    -
    - - - nusoap_base::$xmlEntities
    -
    - - - nusoap_base::$XMLSchemaVersion
    -
    -
    - -
    -
    - - -
    -
    Methods
    - -
    - - -
    - -
    - - addAttachment (line 88) -
    - - -

    adds a MIME attachment to the current request.

    -

    If the $data parameter contains an empty string, this method will read the contents of the file named by the $filename parameter.

    If the $cid parameter is false, this method will generate the cid.

    -
      -
    • return: The content-id (cid) of the attachment
    • -
    • access: public
    • -
    - -
    - string - - addAttachment - - (string $data, [string $filename = ''], [string $contenttype = 'application/octet-stream'], [string $cid = false]) -
    - -
      -
    • - string - $data: The data of the attachment
    • -
    • - string - $filename: The filename of the attachment (default is empty string)
    • -
    • - string - $contenttype: The MIME Content-Type of the attachment (default is application/octet-stream)
    • -
    • - string - $cid: The content-id (cid) of the attachment (default is false)
    • -
    - - -
    - -
    - -
    - - clearAttachments (line 108) -
    - - -

    clears the MIME attachments for the current request.

    -
      -
    • access: public
    • -
    - -
    - void - - clearAttachments - - () -
    - - - -
    - -
    - -
    - - getAttachments (line 122) -
    - - -

    gets the MIME attachments from the current response.

    -

    Each array element in the return is an associative array with keys data, filename, contenttype, cid. These keys correspond to the parameters for addAttachment.

    -
      -
    • return: The attachments.
    • -
    • access: public
    • -
    - -
    - array - - getAttachments - - () -
    - - - -
    - -
    - -
    - - getHTTPBody (line 133) -
    - - -

    gets the HTTP body for the current request.

    -
      -
    • return: The HTTP body, which includes the SOAP payload
    • -
    • access: private
    • -
    - -
    - string - - getHTTPBody - - (string $soapmsg) -
    - -
      -
    • - string - $soapmsg: The SOAP payload
    • -
    - -
    -
    Redefinition of:
    -
    -
    nusoap_client::getHTTPBody()
    -
    gets the HTTP body for the current request.
    -
    - -
    - -
    - -
    - - getHTTPContentType (line 192) -
    - - -

    gets the HTTP content type for the current request.

    -

    Note: getHTTPBody must be called before this.

    -
      -
    • return: the HTTP content type for the current request.
    • -
    • access: private
    • -
    - -
    - string - - getHTTPContentType - - () -
    - - -
    -
    Redefinition of:
    -
    -
    nusoap_client::getHTTPContentType()
    -
    gets the HTTP content type for the current request.
    -
    - -
    - -
    - -
    - - getHTTPContentTypeCharset (line 208) -
    - - -

    gets the HTTP content type charset for the current request.

    -

    returns false for non-text content types.

    Note: getHTTPBody must be called before this.

    -
      -
    • return: the HTTP content type charset for the current request.
    • -
    • access: private
    • -
    - -
    - string - - getHTTPContentTypeCharset - - () -
    - - -
    -
    Redefinition of:
    -
    -
    nusoap_client::getHTTPContentTypeCharset()
    -
    gets the HTTP content type charset for the current request.
    -
    - -
    - -
    - -
    - - parseResponse (line 223) -
    - - -

    processes SOAP message returned from server

    -
      -
    • return: value of the message, decoded into a PHP type
    • -
    • access: private
    • -
    - -
    - mixed - - parseResponse - - (array $headers, string $data) -
    - -
      -
    • - array - $headers: The HTTP headers
    • -
    • - string - $data: unprocessed response data from server
    • -
    - -
    -
    Redefinition of:
    -
    -
    nusoap_client::parseResponse()
    -
    processes SOAP message returned from server
    -
    - -
    -

    Inherited Methods

    - - -

    Inherited From nusoap_client

    -
    -  - nusoap_client::nusoap_client()
    -  - nusoap_client::call()
    -  - nusoap_client::checkCookies()
    -  - nusoap_client::checkWSDL()
    -  - nusoap_client::decodeUTF8()
    -  - nusoap_client::getCookies()
    -  - nusoap_client::getDefaultRpcParams()
    -  - nusoap_client::getHeader()
    -  - nusoap_client::getHeaders()
    -  - nusoap_client::getHTTPBody()
    -  - nusoap_client::getHTTPContentType()
    -  - nusoap_client::getHTTPContentTypeCharset()
    -  - nusoap_client::getOperationData()
    -  - nusoap_client::getProxy()
    -  - nusoap_client::getProxyClassCode()
    -  - nusoap_client::loadWSDL()
    -  - nusoap_client::parseResponse()
    -  - nusoap_client::send()
    -  - nusoap_client::setCookie()
    -  - nusoap_client::setCredentials()
    -  - nusoap_client::setCurlOption()
    -  - nusoap_client::setDefaultRpcParams()
    -  - nusoap_client::setEndpoint()
    -  - nusoap_client::setHeaders()
    -  - nusoap_client::setHTTPEncoding()
    -  - nusoap_client::setHTTPProxy()
    -  - nusoap_client::setUseCURL()
    -  - nusoap_client::UpdateCookies()
    -  - nusoap_client::useHTTPPersistentConnection()
    -  - nusoap_client::_getProxyClassCode()
    -
    - -

    Inherited From nusoap_base

    -
    -  - nusoap_base::nusoap_base()
    -  - nusoap_base::appendDebug()
    -  - nusoap_base::clearDebug()
    -  - nusoap_base::contractQname()
    -  - nusoap_base::debug()
    -  - nusoap_base::expandEntities()
    -  - nusoap_base::expandQname()
    -  - nusoap_base::formatDump()
    -  - nusoap_base::getDebug()
    -  - nusoap_base::getDebugAsXMLComment()
    -  - nusoap_base::getDebugLevel()
    -  - nusoap_base::getError()
    -  - nusoap_base::getGlobalDebugLevel()
    -  - nusoap_base::getLocalPart()
    -  - nusoap_base::getmicrotime()
    -  - nusoap_base::getNamespaceFromPrefix()
    -  - nusoap_base::getPrefix()
    -  - nusoap_base::getPrefixFromNamespace()
    -  - nusoap_base::isArraySimpleOrStruct()
    -  - nusoap_base::serializeEnvelope()
    -  - nusoap_base::serialize_val()
    -  - nusoap_base::setDebugLevel()
    -  - nusoap_base::setError()
    -  - nusoap_base::setGlobalDebugLevel()
    -  - nusoap_base::varDump()
    -  - nusoap_base::__toString()
    -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:10 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/nusoap_fault.html b/lib/nusoap/docs/docs/nusoap/nusoap_fault.html deleted file mode 100644 index e87dfc133..000000000 --- a/lib/nusoap/docs/docs/nusoap/nusoap_fault.html +++ /dev/null @@ -1,457 +0,0 @@ - - - - - - Docs For Class nusoap_fault - - - - -
    -

     Class nusoap_fault

    - - -
    -
    Description
    - -
    - -

    Contains information for a SOAP fault.

    -

    Mainly used for returning faults from deployed functions in a server instance.

    -
      -
    • access: public
    • -
    • version: $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
    • -
    • author: Dietrich Ayala <dietrich@ganx4.com>
    • -
    -

    - Located in /nusoap.php (line 1007) -

    - - -
    nusoap_base
    -   |
    -   --nusoap_fault
    - -
    -
    - - -
    -
    Direct descendents
    - -
    - - - - - - - - - -
    ClassDescription
    -  class - soap_fault - - Backward compatibility -
    -
    -
    - - - -
    -
    Variable Summary
    - -
    -
    -
    -  - string - $faultactor -
    -
    -  - string - $faultcode -
    -
    -  - mixed - $faultdetail -
    -
    -  - string - $faultstring -
    -
    -
    -
    - - -
    -
    Method Summary
    - -
    -
    - -
    -  - nusoap_fault - nusoap_fault - (string $faultcode, [string $faultactor = ''], [string $faultstring = ''], [mixed $faultdetail = '']) -
    - -
    -  - string - serialize - () -
    -
    -
    -
    - - -
    -
    Variables
    - -
    - -
    - -
    - - - string - $faultactor - (line 1019) - -
    - - -

    The fault actor

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - string - $faultcode - (line 1013) - -
    - - -

    The fault code (client|server)

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - mixed - $faultdetail - (line 1031) - -
    - - -

    The fault detail, typically a string or array of string

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - string - $faultstring - (line 1025) - -
    - - -

    The fault string, a description of the fault

    -
      -
    • access: private
    • -
    - - - - - -
    -

    Inherited Variables

    - -

    Inherited from nusoap_base

    -
    - - - nusoap_base::$charencoding
    -
    - - - nusoap_base::$debugLevel
    -
    - - - nusoap_base::$debug_str
    -
    - - - nusoap_base::$error_str
    -
    - - - nusoap_base::$namespaces
    -
    - - - nusoap_base::$revision
    -
    - - - nusoap_base::$soap_defencoding
    -
    - - - nusoap_base::$title
    -
    - - - nusoap_base::$typemap
    -
    - - - nusoap_base::$usedNamespaces
    -
    - - - nusoap_base::$version
    -
    - - - nusoap_base::$xmlEntities
    -
    - - - nusoap_base::$XMLSchemaVersion
    -
    -
    - -
    -
    - - -
    -
    Methods
    - -
    - - -
    - -
    - - Constructor nusoap_fault (line 1041) -
    - - -

    constructor

    - -
    - nusoap_fault - - nusoap_fault - - (string $faultcode, [string $faultactor = ''], [string $faultstring = ''], [mixed $faultdetail = '']) -
    - -
      -
    • - string - $faultcode: (SOAP-ENV:Client | SOAP-ENV:Server)
    • -
    • - string - $faultactor: only used when msg routed between multiple actors
    • -
    • - string - $faultstring: human readable error message
    • -
    • - mixed - $faultdetail: detail, typically a string or array of string
    • -
    - - -
    - -
    - -
    - - serialize (line 1055) -
    - - -

    serialize a fault

    -
      -
    • return: The serialization of the fault instance.
    • -
    • access: public
    • -
    - -
    - string - - serialize - - () -
    - - - -
    -

    Inherited Methods

    - - -

    Inherited From nusoap_base

    -
    -  - nusoap_base::nusoap_base()
    -  - nusoap_base::appendDebug()
    -  - nusoap_base::clearDebug()
    -  - nusoap_base::contractQname()
    -  - nusoap_base::debug()
    -  - nusoap_base::expandEntities()
    -  - nusoap_base::expandQname()
    -  - nusoap_base::formatDump()
    -  - nusoap_base::getDebug()
    -  - nusoap_base::getDebugAsXMLComment()
    -  - nusoap_base::getDebugLevel()
    -  - nusoap_base::getError()
    -  - nusoap_base::getGlobalDebugLevel()
    -  - nusoap_base::getLocalPart()
    -  - nusoap_base::getmicrotime()
    -  - nusoap_base::getNamespaceFromPrefix()
    -  - nusoap_base::getPrefix()
    -  - nusoap_base::getPrefixFromNamespace()
    -  - nusoap_base::isArraySimpleOrStruct()
    -  - nusoap_base::serializeEnvelope()
    -  - nusoap_base::serialize_val()
    -  - nusoap_base::setDebugLevel()
    -  - nusoap_base::setError()
    -  - nusoap_base::setGlobalDebugLevel()
    -  - nusoap_base::varDump()
    -  - nusoap_base::__toString()
    -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:03 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/nusoap_parser.html b/lib/nusoap/docs/docs/nusoap/nusoap_parser.html deleted file mode 100644 index 96b675403..000000000 --- a/lib/nusoap/docs/docs/nusoap/nusoap_parser.html +++ /dev/null @@ -1,1324 +0,0 @@ - - - - - - Docs For Class nusoap_parser - - - - -
    -

     Class nusoap_parser

    - - -
    -
    Description
    - -
    - -

    nusoap_parser class parses SOAP XML messages into native PHP values

    - -

    - Located in /nusoap.php (line 6446) -

    - - -
    nusoap_base
    -   |
    -   --nusoap_parser
    - -
    -
    - - -
    -
    Direct descendents
    - -
    - - - - - - - - - -
    ClassDescription
    -  class - soap_parser - - Backward compatibility -
    -
    -
    - - - -
    -
    Variable Summary
    - -
    -
    -
    -  - mixed - $body_position -
    -
    -  - mixed - $debug_flag -
    -
    -  - mixed - $decode_utf8 -
    -
    -  - mixed - $default_namespace -
    -
    -  - mixed - $depth -
    -
    -  - mixed - $depth_array -
    -
    -  - mixed - $document -
    -
    -  - mixed - $fault -
    -
    -  - mixed - $fault_code -
    -
    -  - mixed - $fault_detail -
    -
    -  - mixed - $fault_str -
    -
    -  - mixed - $ids -
    -
    -  - mixed - $message -
    -
    -  - mixed - $method -
    -
    -  - mixed - $multirefs -
    -
    -  - mixed - $namespaces -
    -
    -  - mixed - $parent -
    -
    -  - mixed - $position -
    -
    -  - mixed - $responseHeaders -
    -
    -  - mixed - $root_header -
    -
    -  - mixed - $root_struct -
    -
    -  - mixed - $root_struct_name -
    -
    -  - mixed - $root_struct_namespace -
    -
    -  - mixed - $soapheader -
    -
    -  - mixed - $soapresponse -
    -
    -  - mixed - $status -
    -
    -  - mixed - $xml -
    -
    -  - mixed - $xml_encoding -
    -
    -
    -
    - - -
    -
    Method Summary
    - -
    -
    - -
    -  - nusoap_parser - nusoap_parser - (string $xml, [string $encoding = 'UTF-8'], [string $method = ''], [string $decode_utf8 = true]) -
    - -
    -  - mixed - buildVal - (integer $pos) -
    - -
    -  - void - character_data - (resource $parser, string $data) -
    - -
    -  - mixed - decodeSimple - (string $value, string $type, string $typens) -
    - -
    -  - void - end_element - (resource $parser, string $name) -
    - -
    -  - string - getHeaders - () -
    - -
    -  - mixed - get_response - () -
    - -
    -  - mixed - get_soapbody - () -
    - -
    -  - mixed - get_soapheader - () -
    - -
    -  - void - start_element - (resource $parser, string $name, array $attrs) -
    -
    -
    -
    - - -
    -
    Variables
    - -
    - -
    - -
    - - - mixed - $body_position - = 0 (line 6473) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $debug_flag - = true (line 6469) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $decode_utf8 - = true (line 6480) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $default_namespace - = '' (line 6460) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $depth - = 0 (line 6459) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $depth_array - = array() (line 6468) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $document - = '' (line 6455) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $fault - = false (line 6464) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $fault_code - = '' (line 6465) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $fault_detail - = '' (line 6467) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $fault_str - = '' (line 6466) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $ids - = array() (line 6476) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $message - = array() (line 6462) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $method - = '' (line 6450) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $multirefs - = array() (line 6478) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $namespaces - = array() (line 6461) - -
    - - - - -
    -
    Redefinition of:
    -
    -
    nusoap_base::$namespaces
    -
    namespaces in an array of prefix => uri
    -
    - - - -
    - -
    - -
    - - - mixed - $parent - = '' (line 6463) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $position - = 0 (line 6458) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $responseHeaders - = '' (line 6472) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $root_header - = '' (line 6454) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $root_struct - = '' (line 6451) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $root_struct_name - = '' (line 6452) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $root_struct_namespace - = '' (line 6453) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $soapheader - = NULL (line 6471) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $soapresponse - = NULL (line 6470) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $status - = '' (line 6457) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $xml - = '' (line 6448) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $xml_encoding - = '' (line 6449) - -
    - - - - - - - -
    -

    Inherited Variables

    - -

    Inherited from nusoap_base

    -
    - - - nusoap_base::$charencoding
    -
    - - - nusoap_base::$debugLevel
    -
    - - - nusoap_base::$debug_str
    -
    - - - nusoap_base::$error_str
    -
    - - - nusoap_base::$revision
    -
    - - - nusoap_base::$soap_defencoding
    -
    - - - nusoap_base::$title
    -
    - - - nusoap_base::$typemap
    -
    - - - nusoap_base::$usedNamespaces
    -
    - - - nusoap_base::$version
    -
    - - - nusoap_base::$xmlEntities
    -
    - - - nusoap_base::$XMLSchemaVersion
    -
    -
    - -
    -
    - - -
    -
    Methods
    - -
    - - -
    - -
    - - Constructor nusoap_parser (line 6491) -
    - - -

    constructor that actually does the parsing

    -
      -
    • access: public
    • -
    - -
    - nusoap_parser - - nusoap_parser - - (string $xml, [string $encoding = 'UTF-8'], [string $method = ''], [string $decode_utf8 = true]) -
    - -
      -
    • - string - $xml: SOAP message
    • -
    • - string - $encoding: character encoding scheme of message
    • -
    • - string - $method: method for which XML is parsed (unused?)
    • -
    • - string - $decode_utf8: whether to decode UTF-8 to ISO-8859-1
    • -
    - - -
    - -
    - -
    - - buildVal (line 6959) -
    - - -

    builds response structures for compound values (arrays/structs) and scalars

    -
      -
    • return: PHP value
    • -
    • access: private
    • -
    - -
    - mixed - - buildVal - - (integer $pos) -
    - -
      -
    • - integer - $pos: position in node tree
    • -
    - - -
    - -
    - -
    - - character_data (line 6846) -
    - - -

    element content handler

    -
      -
    • access: private
    • -
    - -
    - void - - character_data - - (resource $parser, string $data) -
    - -
      -
    • - resource - $parser: XML parser object
    • -
    • - string - $data: element content
    • -
    - - -
    - -
    - -
    - - decodeSimple (line 6915) -
    - - -

    decodes simple types into PHP variables

    -
      -
    • return: PHP value
    • -
    • access: private
    • -
    - -
    - mixed - - decodeSimple - - (string $value, string $type, string $typens) -
    - -
      -
    • - string - $value: value to decode
    • -
    • - string - $type: XML type to decode
    • -
    • - string - $typens: XML type namespace to decode
    • -
    - - -
    - -
    - -
    - - end_element (line 6740) -
    - - -

    end-element handler

    -
      -
    • access: private
    • -
    - -
    - void - - end_element - - (resource $parser, string $name) -
    - -
      -
    • - resource - $parser: XML parser object
    • -
    • - string - $name: element name
    • -
    - - -
    - -
    - -
    - - getHeaders (line 6902) -
    - - -

    get the unparsed SOAP Header

    -
      -
    • return: XML or empty if no Header
    • -
    • access: public
    • -
    - -
    - string - - getHeaders - - () -
    - - - -
    - -
    - -
    - - get_response (line 6872) -
    - - -

    get the parsed message (SOAP Body)

    -
      -
    • deprecated: use get_soapbody instead
    • -
    • access: public
    • -
    - -
    - mixed - - get_response - - () -
    - - - -
    - -
    - -
    - - get_soapbody (line 6882) -
    - - -

    get the parsed SOAP Body (NULL if there was none)

    -
      -
    • access: public
    • -
    - -
    - mixed - - get_soapbody - - () -
    - - - -
    - -
    - -
    - - get_soapheader (line 6892) -
    - - -

    get the parsed SOAP Header (NULL if there was none)

    -
      -
    • access: public
    • -
    - -
    - mixed - - get_soapheader - - () -
    - - - -
    - -
    - -
    - - start_element (line 6585) -
    - - -

    start-element handler

    -
      -
    • access: private
    • -
    - -
    - void - - start_element - - (resource $parser, string $name, array $attrs) -
    - -
      -
    • - resource - $parser: XML parser object
    • -
    • - string - $name: element name
    • -
    • - array - $attrs: associative array of attributes
    • -
    - - -
    -

    Inherited Methods

    - - -

    Inherited From nusoap_base

    -
    -  - nusoap_base::nusoap_base()
    -  - nusoap_base::appendDebug()
    -  - nusoap_base::clearDebug()
    -  - nusoap_base::contractQname()
    -  - nusoap_base::debug()
    -  - nusoap_base::expandEntities()
    -  - nusoap_base::expandQname()
    -  - nusoap_base::formatDump()
    -  - nusoap_base::getDebug()
    -  - nusoap_base::getDebugAsXMLComment()
    -  - nusoap_base::getDebugLevel()
    -  - nusoap_base::getError()
    -  - nusoap_base::getGlobalDebugLevel()
    -  - nusoap_base::getLocalPart()
    -  - nusoap_base::getmicrotime()
    -  - nusoap_base::getNamespaceFromPrefix()
    -  - nusoap_base::getPrefix()
    -  - nusoap_base::getPrefixFromNamespace()
    -  - nusoap_base::isArraySimpleOrStruct()
    -  - nusoap_base::serializeEnvelope()
    -  - nusoap_base::serialize_val()
    -  - nusoap_base::setDebugLevel()
    -  - nusoap_base::setError()
    -  - nusoap_base::setGlobalDebugLevel()
    -  - nusoap_base::varDump()
    -  - nusoap_base::__toString()
    -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:03 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/nusoap_server.html b/lib/nusoap/docs/docs/nusoap/nusoap_server.html deleted file mode 100644 index 1204b6081..000000000 --- a/lib/nusoap/docs/docs/nusoap/nusoap_server.html +++ /dev/null @@ -1,1620 +0,0 @@ - - - - - - Docs For Class nusoap_server - - - - -
    -

     Class nusoap_server

    - - -
    -
    Description
    - -
    - -

    nusoap_server allows the user to create a SOAP server that is capable of receiving messages and returning responses

    - -

    - Located in /nusoap.php (line 3473) -

    - - -
    nusoap_base
    -   |
    -   --nusoap_server
    - -
    -
    - - -
    -
    Direct descendents
    - -
    - - - - - - - - - - - - - -
    ClassDescription
    -  class - soap_server - - Backward compatibility -
    -  class - nusoap_server_mime - - nusoap_server_mime server supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library. -
    -
    -
    - - - -
    -
    Variable Summary
    - -
    -
    -
    -  - boolean - $debug_flag -
    -
    -  - boolean - $decode_utf8 -
    -
    -  - string - $document -
    -
    -  - mixed - $externalWSDLURL -
    -
    -  - mixed - $fault -
    -
    -  - array - $headers -
    -
    -  - string - $methodname -
    -
    -  - array - $methodparams -
    -
    -  - mixed - $methodreturn -
    -
    -  - boolean - $methodreturnisliteralxml -
    -
    -  - string - $methodURI -
    -
    -  - array - $operations -
    -
    -  - array - $outgoing_headers -
    -
    -  - string - $request -
    -
    -  - mixed - $requestHeader -
    -
    -  - string - $requestHeaders -
    -
    -  - string - $requestSOAP -
    -
    -  - string - $response -
    -
    -  - mixed - $responseHeaders -
    -
    -  - string - $responseSOAP -
    -
    -  - string - $result -
    -
    -  - string - $SOAPAction -
    -
    -  - mixed - $wsdl -
    -
    -  - string - $xml_encoding -
    -
    -
    -
    - - -
    -
    Method Summary
    - -
    -
    - -
    -  - nusoap_server - nusoap_server - ([mixed $wsdl = false]) -
    - -
    -  - void - add_to_map - (string $methodname, string $in, string $out) -
    - -
    -  - void - configureWSDL - (mixed $serviceName, [mixed $namespace = false], [mixed $endpoint = false], [string $style = 'rpc'], [string $transport = 'http://schemas.xmlsoap.org/soap/http'], [mixed $schemaTargetNamespace = false], string $serviceName,) -
    - -
    -  - void - fault - (string $faultcode, string $faultstring, [string $faultactor = ''], [string $faultdetail = '']) -
    - -
    -  - string - getHTTPBody - (string $soapmsg) -
    - -
    -  - string - getHTTPContentType - () -
    - -
    -  - string - getHTTPContentTypeCharset - () -
    - -
    -  - void - invoke_method - () -
    - -
    -  - mixed - parseRequest - (array $headers, string $data) -
    - -
    -  - void - parse_http_headers - () -
    - -
    -  - void - parse_request - ([string $data = '']) -
    - -
    -  - void - register - (string $name, [array $in = array()], [array $out = array()], [mixed $namespace = false], [mixed $soapaction = false], [mixed $style = false], [mixed $use = false], [string $documentation = ''], [string $encodingStyle = '']) -
    - -
    -  - void - send_response - () -
    - -
    -  - void - serialize_return - () -
    - -
    -  - void - service - (string $data) -
    - -
    -  - boolean - verify_method - (string $operation, array $request) -
    -
    -
    -
    - - -
    -
    Variables
    - -
    - -
    - -
    - - - boolean - $debug_flag - = false (line 3620) - -
    - - -

    whether to append debug to response as XML comment

    -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - boolean - $decode_utf8 - = true (line 3545) - -
    - - -

    toggles whether the parser decodes element content w/ utf8_decode()

    -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - string - $document - = '' (line 3503) - -
    - - -

    SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)

    -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - mixed - $externalWSDLURL - = false (line 3614) - -
    - - -

    URL for WSDL (if one)

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - mixed - $fault - = false (line 3588) - -
    - - -

    SOAP fault for response (or false)

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - array - $headers - = array() (line 3479) - -
    - - -

    HTTP headers of request

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - string - $methodname - = '' (line 3521) - -
    - - -

    name of method requested

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - array - $methodparams - = array() (line 3527) - -
    - - -

    method parameters from request

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - mixed - $methodreturn - = false (line 3576) - -
    - - -

    method return value to place in response

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - boolean - $methodreturnisliteralxml - = false (line 3582) - -
    - - -

    whether $methodreturn is a string of literal XML

    -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - string - $methodURI - = '' (line 3515) - -
    - - -

    requested method namespace URI

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - array - $operations - = array() (line 3602) - -
    - - -

    assoc array of operations => opData; operations are added by the register()

    -

    method or by parsing an external WSDL definition

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - array - $outgoing_headers - = array() (line 3552) - -
    - - -

    HTTP headers of response

    -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - string - $request - = '' (line 3485) - -
    - - -

    HTTP request

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - mixed - $requestHeader - = NULL (line 3497) - -
    - - -

    SOAP Headers from request (parsed)

    -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - string - $requestHeaders - = '' (line 3491) - -
    - - -

    SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)

    -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - string - $requestSOAP - = '' (line 3509) - -
    - - -

    SOAP payload for request (text)

    -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - string - $response - = '' (line 3558) - -
    - - -

    HTTP response

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - mixed - $responseHeaders - = '' (line 3564) - -
    - - -

    SOAP headers for response (text or array of soapval or associative array)

    -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - string - $responseSOAP - = '' (line 3570) - -
    - - -

    SOAP payload for response (text)

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - string - $result - = 'successful' (line 3594) - -
    - - -

    text indication of result (for debugging)

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - string - $SOAPAction - = '' (line 3533) - -
    - - -

    SOAP Action from request

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - mixed - $wsdl - = false (line 3608) - -
    - - -

    wsdl instance (if one)

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - string - $xml_encoding - = '' (line 3539) - -
    - - -

    character set encoding of incoming (request) messages

    -
      -
    • access: public
    • -
    - - - - - -
    -

    Inherited Variables

    - -

    Inherited from nusoap_base

    -
    - - - nusoap_base::$charencoding
    -
    - - - nusoap_base::$debugLevel
    -
    - - - nusoap_base::$debug_str
    -
    - - - nusoap_base::$error_str
    -
    - - - nusoap_base::$namespaces
    -
    - - - nusoap_base::$revision
    -
    - - - nusoap_base::$soap_defencoding
    -
    - - - nusoap_base::$title
    -
    - - - nusoap_base::$typemap
    -
    - - - nusoap_base::$usedNamespaces
    -
    - - - nusoap_base::$version
    -
    - - - nusoap_base::$xmlEntities
    -
    - - - nusoap_base::$XMLSchemaVersion
    -
    -
    - -
    -
    - - -
    -
    Methods
    - -
    - - -
    - -
    - - Constructor nusoap_server (line 3630) -
    - - -

    constructor the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.

    -
      -
    • access: public
    • -
    - -
    - nusoap_server - - nusoap_server - - ([mixed $wsdl = false]) -
    - -
      -
    • - mixed - $wsdl: file path or URL (string), or wsdl instance (object)
    • -
    - - -
    - -
    - -
    - - add_to_map (line 4399) -
    - - -

    add a method to the dispatch map (this has been replaced by the register method)

    -
      -
    • deprecated:
    • -
    • access: public
    • -
    - -
    - void - - add_to_map - - (string $methodname, string $in, string $out) -
    - -
      -
    • - string - $methodname
    • -
    • - string - $in: array of input values
    • -
    • - string - $out: array of output values
    • -
    - - -
    - -
    - -
    - - configureWSDL (line 4505) -
    - - -

    Sets up wsdl object.

    -

    Acts as a flag to enable internal WSDL generation

    - -
    - void - - configureWSDL - - (mixed $serviceName, [mixed $namespace = false], [mixed $endpoint = false], [string $style = 'rpc'], [string $transport = 'http://schemas.xmlsoap.org/soap/http'], [mixed $schemaTargetNamespace = false], string $serviceName,) -
    - -
      -
    • - string - $serviceName,: name of the service
    • -
    • - mixed - $namespace: optional 'tns' service namespace or false
    • -
    • - mixed - $endpoint: optional URL of service endpoint or false
    • -
    • - string - $style: optional (rpc|document) WSDL style (also specified by operation)
    • -
    • - string - $transport: optional SOAP transport
    • -
    • - mixed - $schemaTargetNamespace: optional 'types' targetNamespace for service schema or false
    • -
    - - -
    - -
    - -
    - - fault (line 4486) -
    - - -

    Specify a fault to be returned to the client.

    -

    This also acts as a flag to the server that a fault has occured.

    -
      -
    • access: public
    • -
    - -
    - void - - fault - - (string $faultcode, string $faultstring, [string $faultactor = ''], [string $faultdetail = '']) -
    - -
      -
    • - string - $faultcode
    • -
    • - string - $faultstring
    • -
    • - string - $faultactor
    • -
    • - string - $faultdetail
    • -
    - - -
    - -
    - -
    - - getHTTPBody (line 4361) -
    - - -

    gets the HTTP body for the current response.

    -
      -
    • return: The HTTP body, which includes the SOAP payload
    • -
    • access: private
    • -
    - -
    - string - - getHTTPBody - - (string $soapmsg) -
    - -
      -
    • - string - $soapmsg: The SOAP payload
    • -
    - - -
    -
    Redefined in descendants as:
    - -
    - -
    - -
    - - getHTTPContentType (line 4373) -
    - - -

    gets the HTTP content type for the current response.

    -

    Note: getHTTPBody must be called before this.

    -
      -
    • return: the HTTP content type for the current response.
    • -
    • access: private
    • -
    - -
    - string - - getHTTPContentType - - () -
    - - - -
    -
    Redefined in descendants as:
    - -
    - -
    - -
    - - getHTTPContentTypeCharset (line 4386) -
    - - -

    gets the HTTP content type charset for the current response.

    -

    returns false for non-text content types.

    Note: getHTTPBody must be called before this.

    -
      -
    • return: the HTTP content type charset for the current response.
    • -
    • access: private
    • -
    - -
    - string - - getHTTPContentTypeCharset - - () -
    - - - -
    -
    Redefined in descendants as:
    - -
    - -
    - -
    - - invoke_method (line 3950) -
    - - -

    invokes a PHP function for the requested SOAP method

    -

    The following fields are set by this function (when successful)

    methodreturn

    Note that the PHP function that is called may also set the following fields to affect the response sent to the client

    responseHeaders outgoing_headers

    This sets the fault field on error

    -
      -
    • access: private
    • -
    - -
    - void - - invoke_method - - () -
    - - - -
    - -
    - -
    - - parseRequest (line 4305) -
    - - -

    processes SOAP message received from client

    -
      -
    • return: value of the message, decoded into a PHP type
    • -
    • access: private
    • -
    - -
    - mixed - - parseRequest - - (array $headers, string $data) -
    - -
      -
    • - array - $headers: The HTTP headers
    • -
    • - string - $data: unprocessed request data from client
    • -
    - - -
    -
    Redefined in descendants as:
    - -
    - -
    - -
    - - parse_http_headers (line 3777) -
    - - -

    parses HTTP request headers.

    -

    The following fields are set by this function (when successful)

    headers request xml_encoding SOAPAction

    -
      -
    • access: private
    • -
    - -
    - void - - parse_http_headers - - () -
    - - - -
    - -
    - -
    - - parse_request (line 3903) -
    - - -

    parses a request

    -

    The following fields are set by this function (when successful)

    headers request xml_encoding SOAPAction request requestSOAP methodURI methodname methodparams requestHeaders document

    This sets the fault field on error

    -
      -
    • access: private
    • -
    - -
    - void - - parse_request - - ([string $data = '']) -
    - -
      -
    • - string - $data: XML string
    • -
    - - -
    - -
    - -
    - - register (line 4417) -
    - - -

    register a service function with the server

    -
      -
    • access: public
    • -
    - -
    - void - - register - - (string $name, [array $in = array()], [array $out = array()], [mixed $namespace = false], [mixed $soapaction = false], [mixed $style = false], [mixed $use = false], [string $documentation = ''], [string $encodingStyle = '']) -
    - -
      -
    • - string - $name: the name of the PHP function, class.method or class..method
    • -
    • - array - $in: assoc array of input values: key = param name, value = param type
    • -
    • - array - $out: assoc array of output values: key = param name, value = param type
    • -
    • - mixed - $namespace: the element namespace for the method or false
    • -
    • - mixed - $soapaction: the soapaction for the method or false
    • -
    • - mixed - $style: optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
    • -
    • - mixed - $use: optional (encoded|literal) or false
    • -
    • - string - $documentation: optional Description to include in WSDL
    • -
    • - string - $encodingStyle: optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
    • -
    - - -
    - -
    - -
    - - send_response (line 4207) -
    - - -

    sends an HTTP response

    -

    The following fields are set by this function (when successful)

    outgoing_headers response

    -
      -
    • access: private
    • -
    - -
    - void - - send_response - - () -
    - - - -
    - -
    - -
    - - serialize_return (line 4107) -
    - - -

    serializes the return value from a PHP function into a full SOAP Envelope

    -

    The following fields are set by this function (when successful)

    responseSOAP

    This sets the fault field on error

    -
      -
    • access: private
    • -
    - -
    - void - - serialize_return - - () -
    - - - -
    - -
    - -
    - - service (line 3693) -
    - - -

    processes request and returns response

    -
      -
    • access: public
    • -
    - -
    - void - - service - - (string $data) -
    - -
      -
    • - string - $data: usually is the value of $HTTP_RAW_POST_DATA
    • -
    - - -
    - -
    - -
    - - verify_method (line 4286) -
    - - -

    takes the value that was created by parsing the request and compares to the method's signature, if available.

    -
      -
    • return: Whether the operation was found
    • -
    • access: private
    • -
    - -
    - boolean - - verify_method - - (string $operation, array $request) -
    - -
      -
    • - string - $operation: The operation to be invoked
    • -
    • - array - $request: The array of parameter values
    • -
    - - -
    -

    Inherited Methods

    - - -

    Inherited From nusoap_base

    -
    -  - nusoap_base::nusoap_base()
    -  - nusoap_base::appendDebug()
    -  - nusoap_base::clearDebug()
    -  - nusoap_base::contractQname()
    -  - nusoap_base::debug()
    -  - nusoap_base::expandEntities()
    -  - nusoap_base::expandQname()
    -  - nusoap_base::formatDump()
    -  - nusoap_base::getDebug()
    -  - nusoap_base::getDebugAsXMLComment()
    -  - nusoap_base::getDebugLevel()
    -  - nusoap_base::getError()
    -  - nusoap_base::getGlobalDebugLevel()
    -  - nusoap_base::getLocalPart()
    -  - nusoap_base::getmicrotime()
    -  - nusoap_base::getNamespaceFromPrefix()
    -  - nusoap_base::getPrefix()
    -  - nusoap_base::getPrefixFromNamespace()
    -  - nusoap_base::isArraySimpleOrStruct()
    -  - nusoap_base::serializeEnvelope()
    -  - nusoap_base::serialize_val()
    -  - nusoap_base::setDebugLevel()
    -  - nusoap_base::setError()
    -  - nusoap_base::setGlobalDebugLevel()
    -  - nusoap_base::varDump()
    -  - nusoap_base::__toString()
    -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:04 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/nusoap_server_mime.html b/lib/nusoap/docs/docs/nusoap/nusoap_server_mime.html deleted file mode 100644 index cc388955e..000000000 --- a/lib/nusoap/docs/docs/nusoap/nusoap_server_mime.html +++ /dev/null @@ -1,774 +0,0 @@ - - - - - - Docs For Class nusoap_server_mime - - - - -
    -

     Class nusoap_server_mime

    - - -
    -
    Description
    - -
    - -

    nusoap_server_mime server supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.

    -
      -
    • access: public
    • -
    • version: $Id: nusoapmime.php,v 1.13 2010/04/26 20:15:08 snichol Exp $
    • -
    • author: Scott Nichol <snichol@users.sourceforge.net>
    • -
    • author: Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
    • -
    -

    - Located in /nusoapmime.php (line 284) -

    - - -
    nusoap_base
    -   |
    -   --nusoap_server
    -      |
    -      --nusoap_server_mime
    - -
    -
    - - -
    -
    Direct descendents
    - -
    - - - - - - - - - -
    ClassDescription
    -  class - nusoapservermime - - nusoap_server_mime server supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library. -
    -
    -
    - - - -
    -
    Variable Summary
    - -
    -
    -
    -  - string - $mimeContentType -
    -
    -  - array - $requestAttachments -
    -
    -  - array - $responseAttachments -
    -
    -
    -
    - - -
    -
    Method Summary
    - -
    -
    - -
    -  - string - addAttachment - (string $data, [string $filename = ''], [string $contenttype = 'application/octet-stream'], [string $cid = false]) -
    - -
    -  - void - clearAttachments - () -
    - -
    -  - array - getAttachments - () -
    - -
    -  - string - getHTTPBody - (string $soapmsg) -
    - -
    -  - string - getHTTPContentType - () -
    - -
    -  - string - getHTTPContentTypeCharset - () -
    - -
    -  - mixed - parseRequest - (array $headers, string $data) -
    -
    -
    -
    - - -
    -
    Variables
    - -
    - -
    - -
    - - - string - $mimeContentType - (line 301) - -
    - - -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - array - $requestAttachments - = array() (line 290) - -
    - - -
      -
    • var: Each array element in the return is an associative array with keys data, filename, contenttype, cid
    • -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - array - $responseAttachments - (line 296) - -
    - - -
      -
    • var: Each array element in the return is an associative array with keys data, filename, contenttype, cid
    • -
    • access: private
    • -
    - - - - - -
    -

    Inherited Variables

    - -

    Inherited from nusoap_server

    -
    - - - nusoap_server::$debug_flag
    -
    - - - nusoap_server::$decode_utf8
    -
    - - - nusoap_server::$document
    -
    - - - nusoap_server::$externalWSDLURL
    -
    - - - nusoap_server::$fault
    -
    - - - nusoap_server::$headers
    -
    - - - nusoap_server::$methodname
    -
    - - - nusoap_server::$methodparams
    -
    - - - nusoap_server::$methodreturn
    -
    - - - nusoap_server::$methodreturnisliteralxml
    -
    - - - nusoap_server::$methodURI
    -
    - - - nusoap_server::$operations
    -
    - - - nusoap_server::$outgoing_headers
    -
    - - - nusoap_server::$request
    -
    - - - nusoap_server::$requestHeader
    -
    - - - nusoap_server::$requestHeaders
    -
    - - - nusoap_server::$requestSOAP
    -
    - - - nusoap_server::$response
    -
    - - - nusoap_server::$responseHeaders
    -
    - - - nusoap_server::$responseSOAP
    -
    - - - nusoap_server::$result
    -
    - - - nusoap_server::$SOAPAction
    -
    - - - nusoap_server::$wsdl
    -
    - - - nusoap_server::$xml_encoding
    -
    -
    -

    Inherited from nusoap_base

    -
    - - - nusoap_base::$charencoding
    -
    - - - nusoap_base::$debugLevel
    -
    - - - nusoap_base::$debug_str
    -
    - - - nusoap_base::$error_str
    -
    - - - nusoap_base::$namespaces
    -
    - - - nusoap_base::$revision
    -
    - - - nusoap_base::$soap_defencoding
    -
    - - - nusoap_base::$title
    -
    - - - nusoap_base::$typemap
    -
    - - - nusoap_base::$usedNamespaces
    -
    - - - nusoap_base::$version
    -
    - - - nusoap_base::$xmlEntities
    -
    - - - nusoap_base::$XMLSchemaVersion
    -
    -
    - -
    -
    - - -
    -
    Methods
    - -
    - - -
    - -
    - - addAttachment (line 318) -
    - - -

    adds a MIME attachment to the current response.

    -

    If the $data parameter contains an empty string, this method will read the contents of the file named by the $filename parameter.

    If the $cid parameter is false, this method will generate the cid.

    -
      -
    • return: The content-id (cid) of the attachment
    • -
    • access: public
    • -
    - -
    - string - - addAttachment - - (string $data, [string $filename = ''], [string $contenttype = 'application/octet-stream'], [string $cid = false]) -
    - -
      -
    • - string - $data: The data of the attachment
    • -
    • - string - $filename: The filename of the attachment (default is empty string)
    • -
    • - string - $contenttype: The MIME Content-Type of the attachment (default is application/octet-stream)
    • -
    • - string - $cid: The content-id (cid) of the attachment (default is false)
    • -
    - - -
    - -
    - -
    - - clearAttachments (line 338) -
    - - -

    clears the MIME attachments for the current response.

    -
      -
    • access: public
    • -
    - -
    - void - - clearAttachments - - () -
    - - - -
    - -
    - -
    - - getAttachments (line 352) -
    - - -

    gets the MIME attachments from the current request.

    -

    Each array element in the return is an associative array with keys data, filename, contenttype, cid. These keys correspond to the parameters for addAttachment.

    -
      -
    • return: The attachments.
    • -
    • access: public
    • -
    - -
    - array - - getAttachments - - () -
    - - - -
    - -
    - -
    - - getHTTPBody (line 363) -
    - - -

    gets the HTTP body for the current response.

    -
      -
    • return: The HTTP body, which includes the SOAP payload
    • -
    • access: private
    • -
    - -
    - string - - getHTTPBody - - (string $soapmsg) -
    - -
      -
    • - string - $soapmsg: The SOAP payload
    • -
    - -
    -
    Redefinition of:
    -
    -
    nusoap_server::getHTTPBody()
    -
    gets the HTTP body for the current response.
    -
    - -
    - -
    - -
    - - getHTTPContentType (line 422) -
    - - -

    gets the HTTP content type for the current response.

    -

    Note: getHTTPBody must be called before this.

    -
      -
    • return: the HTTP content type for the current response.
    • -
    • access: private
    • -
    - -
    - string - - getHTTPContentType - - () -
    - - -
    -
    Redefinition of:
    -
    -
    nusoap_server::getHTTPContentType()
    -
    gets the HTTP content type for the current response.
    -
    - -
    - -
    - -
    - - getHTTPContentTypeCharset (line 438) -
    - - -

    gets the HTTP content type charset for the current response.

    -

    returns false for non-text content types.

    Note: getHTTPBody must be called before this.

    -
      -
    • return: the HTTP content type charset for the current response.
    • -
    • access: private
    • -
    - -
    - string - - getHTTPContentTypeCharset - - () -
    - - -
    -
    Redefinition of:
    -
    -
    nusoap_server::getHTTPContentTypeCharset()
    -
    gets the HTTP content type charset for the current response.
    -
    - -
    - -
    - -
    - - parseRequest (line 453) -
    - - -

    processes SOAP message received from client

    -
      -
    • return: value of the message, decoded into a PHP type
    • -
    • access: private
    • -
    - -
    - mixed - - parseRequest - - (array $headers, string $data) -
    - -
      -
    • - array - $headers: The HTTP headers
    • -
    • - string - $data: unprocessed request data from client
    • -
    - -
    -
    Redefinition of:
    -
    -
    nusoap_server::parseRequest()
    -
    processes SOAP message received from client
    -
    - -
    -

    Inherited Methods

    - - -

    Inherited From nusoap_server

    -
    -  - nusoap_server::nusoap_server()
    -  - nusoap_server::add_to_map()
    -  - nusoap_server::configureWSDL()
    -  - nusoap_server::fault()
    -  - nusoap_server::getHTTPBody()
    -  - nusoap_server::getHTTPContentType()
    -  - nusoap_server::getHTTPContentTypeCharset()
    -  - nusoap_server::invoke_method()
    -  - nusoap_server::parseRequest()
    -  - nusoap_server::parse_http_headers()
    -  - nusoap_server::parse_request()
    -  - nusoap_server::register()
    -  - nusoap_server::send_response()
    -  - nusoap_server::serialize_return()
    -  - nusoap_server::service()
    -  - nusoap_server::verify_method()
    -
    - -

    Inherited From nusoap_base

    -
    -  - nusoap_base::nusoap_base()
    -  - nusoap_base::appendDebug()
    -  - nusoap_base::clearDebug()
    -  - nusoap_base::contractQname()
    -  - nusoap_base::debug()
    -  - nusoap_base::expandEntities()
    -  - nusoap_base::expandQname()
    -  - nusoap_base::formatDump()
    -  - nusoap_base::getDebug()
    -  - nusoap_base::getDebugAsXMLComment()
    -  - nusoap_base::getDebugLevel()
    -  - nusoap_base::getError()
    -  - nusoap_base::getGlobalDebugLevel()
    -  - nusoap_base::getLocalPart()
    -  - nusoap_base::getmicrotime()
    -  - nusoap_base::getNamespaceFromPrefix()
    -  - nusoap_base::getPrefix()
    -  - nusoap_base::getPrefixFromNamespace()
    -  - nusoap_base::isArraySimpleOrStruct()
    -  - nusoap_base::serializeEnvelope()
    -  - nusoap_base::serialize_val()
    -  - nusoap_base::setDebugLevel()
    -  - nusoap_base::setError()
    -  - nusoap_base::setGlobalDebugLevel()
    -  - nusoap_base::varDump()
    -  - nusoap_base::__toString()
    -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:10 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/nusoap_wsdlcache.html b/lib/nusoap/docs/docs/nusoap/nusoap_wsdlcache.html deleted file mode 100644 index 20aa98815..000000000 --- a/lib/nusoap/docs/docs/nusoap/nusoap_wsdlcache.html +++ /dev/null @@ -1,568 +0,0 @@ - - - - - - Docs For Class nusoap_wsdlcache - - - - -
    -

     Class nusoap_wsdlcache

    - - -
    -
    Description
    - -
    - -

    caches instances of the wsdl class

    - -

    - Located in /class.wsdlcache.php (line 18) -

    - - -
    
    -	
    -			
    -
    - - -
    -
    Direct descendents
    - -
    - - - - - - - - - -
    ClassDescription
    -  class - wsdlcache - - For backward compatibility -
    -
    -
    - - - -
    -
    Variable Summary
    - -
    -
    -
    -  - string - $cache_dir -
    -
    -  - integer - $cache_lifetime -
    -
    -  - string - $debug_str -
    -
    -  - resource - $fplock -
    -
    -
    -
    - - -
    -
    Method Summary
    - -
    -
    - -
    -  - nusoap_wsdlcache - nusoap_wsdlcache - ([string $cache_dir = '.'], integer $cache_lifetime) -
    - -
    -  - string - createFilename - (string $wsdl) -
    - -
    -  - void - debug - (string $string) -
    - -
    -  - object wsdl - get - (string $wsdl) -
    - -
    -  - boolean - obtainMutex - (string $filename, string $mode) -
    - -
    -  - boolean - put - (object wsdl $wsdl_instance) -
    - -
    -  - boolean - releaseMutex - (string $filename) -
    - -
    -  - boolean - remove - (string $wsdl) -
    -
    -
    -
    - - -
    -
    Variables
    - -
    - -
    - -
    - - - string - $cache_dir - (line 33) - -
    - - -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - integer - $cache_lifetime - (line 28) - -
    - - -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - string - $debug_str - = '' (line 38) - -
    - - -
      -
    • access: public
    • -
    - - - - - -
    - -
    - -
    - - - resource - $fplock - (line 23) - -
    - - -
      -
    • access: private
    • -
    - - - - - -
    - -
    -
    - - -
    -
    Methods
    - -
    - - -
    - -
    - - Constructor nusoap_wsdlcache (line 47) -
    - - -

    constructor

    -
      -
    • access: public
    • -
    - -
    - nusoap_wsdlcache - - nusoap_wsdlcache - - ([string $cache_dir = '.'], integer $cache_lifetime) -
    - -
      -
    • - string - $cache_dir: directory for cache-files
    • -
    • - integer - $cache_lifetime: lifetime for caching-files in seconds or 0 for unlimited
    • -
    - - -
    - -
    - -
    - - createFilename (line 60) -
    - - -

    creates the filename used to cache a wsdl instance

    -
      -
    • return: The filename used to cache the instance
    • -
    • access: private
    • -
    - -
    - string - - createFilename - - (string $wsdl) -
    - -
      -
    • - string - $wsdl: The URL of the wsdl instance
    • -
    - - -
    - -
    - -
    - - debug (line 70) -
    - - -

    adds debug data to the class level debug string

    -
      -
    • access: private
    • -
    - -
    - void - - debug - - (string $string) -
    - -
      -
    • - string - $string: debug data
    • -
    - - -
    - -
    - -
    - - get (line 81) -
    - - -

    gets a wsdl instance from the cache

    -
      -
    • return: The cached wsdl instance, null if the instance is not in the cache
    • -
    • access: public
    • -
    - -
    - object wsdl - - get - - (string $wsdl) -
    - -
      -
    • - string - $wsdl: The URL of the wsdl instance
    • -
    - - -
    - -
    - -
    - - obtainMutex (line 124) -
    - - -

    obtains the local mutex

    -
      -
    • return: Lock successfully obtained ?!
    • -
    • access: private
    • -
    - -
    - boolean - - obtainMutex - - (string $filename, string $mode) -
    - -
      -
    • - string - $filename: The Filename of the Cache to lock
    • -
    • - string - $mode: The open-mode ("r" or "w") or the file - affects lock-mode
    • -
    - - -
    - -
    - -
    - - put (line 144) -
    - - -

    adds a wsdl instance to the cache

    -
      -
    • return: WSDL successfully cached
    • -
    • access: public
    • -
    - -
    - boolean - - put - - (object wsdl $wsdl_instance) -
    - -
      -
    • - object wsdl - $wsdl_instance: The wsdl instance to add
    • -
    - - -
    - -
    - -
    - - releaseMutex (line 172) -
    - - -

    releases the local mutex

    -
      -
    • return: Lock successfully released
    • -
    • access: private
    • -
    - -
    - boolean - - releaseMutex - - (string $filename) -
    - -
      -
    • - string - $filename: The Filename of the Cache to lock
    • -
    - - -
    - -
    - -
    - - remove (line 189) -
    - - -

    removes a wsdl instance from the cache

    -
      -
    • return: Whether there was an instance to remove
    • -
    • access: public
    • -
    - -
    - boolean - - remove - - (string $wsdl) -
    - -
      -
    • - string - $wsdl: The URL of the wsdl instance
    • -
    - - -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:16:49 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/nusoap_xmlschema.html b/lib/nusoap/docs/docs/nusoap/nusoap_xmlschema.html deleted file mode 100644 index d01415b07..000000000 --- a/lib/nusoap/docs/docs/nusoap/nusoap_xmlschema.html +++ /dev/null @@ -1,1462 +0,0 @@ - - - - - - Docs For Class nusoap_xmlschema - - - - -
    -

     Class nusoap_xmlschema

    - - -
    -
    Description
    - -
    - -

    parses an XML Schema, allows access to it's data, other utility methods.

    -

    imperfect, no validation... yet, but quite functional.

    - -

    - Located in /nusoap.php (line 1095) -

    - - -
    nusoap_base
    -   |
    -   --nusoap_xmlschema
    - -
    -
    - - -
    -
    Direct descendents
    - -
    - - - - - - - - - -
    ClassDescription
    -  class - XMLSchema - - Backward compatibility -
    -
    -
    - - - -
    -
    Variable Summary
    - -
    -
    -
    -  - mixed - $attributes -
    -
    -  - mixed - $complexTypes -
    -
    -  - mixed - $complexTypeStack -
    -
    -  - mixed - $currentComplexType -
    -
    -  - mixed - $currentElement -
    -
    -  - mixed - $currentSimpleType -
    -
    -  - mixed - $defaultNamespace -
    -
    -  - mixed - $depth -
    -
    -  - mixed - $depth_array -
    -
    -  - mixed - $elements -
    -
    -  - mixed - $elementStack -
    -
    -  - mixed - $enclosingNamespaces -
    -
    -  - mixed - $imports -
    -
    -  - mixed - $message -
    -
    -  - mixed - $parser -
    -
    -  - mixed - $position -
    -
    -  - mixed - $schema -
    -
    -  - mixed - $schemaInfo -
    -
    -  - mixed - $schemaTargetNamespace -
    -
    -  - mixed - $simpleTypes -
    -
    -  - mixed - $simpleTypeStack -
    -
    -  - mixed - $xml -
    -
    -
    -
    - - -
    -
    Method Summary
    - -
    -
    - -
    -  - nusoap_xmlschema - nusoap_xmlschema - ([string $schema = ''], [string $xml = ''], [string $namespaces = array()]) -
    - -
    -  - void - addComplexType - (name $name, [typeClass $typeClass = 'complexType'], [phpType: $phpType = 'array'], [compositor $compositor = ''], [restrictionBase $restrictionBase = ''], [elements $elements = array()], [attrs $attrs = array()], [arrayType: $arrayType = '']) -
    - -
    -  - void - addElement - (array $attrs) -
    - -
    -  - void - addSimpleType - (string $name, [string $restrictionBase = ''], [string $typeClass = 'simpleType'], [string $phpType = 'scalar'], [array $enumeration = array()]) -
    - -
    -  - string - CreateTypeName - (string $ename) -
    - -
    -  - mixed - getPHPType - (string $type, string $ns) -
    - -
    -  - mixed - getTypeDef - (string $type) -
    - -
    -  - boolean - parseFile - (string $xml, string $type) -
    - -
    -  - void - parseString - (string $xml, string $type) -
    - -
    -  - void - schemaCharacterData - (string $parser, string $data) -
    - -
    -  - void - schemaEndElement - (string $parser, string $name) -
    - -
    -  - void - schemaStartElement - (string $parser, string $name, string $attrs) -
    - -
    -  - void - serializeSchema - () -
    - -
    -  - mixed - serializeTypeDef - (string $type) -
    - -
    -  - string - typeToForm - (string $name, string $type) -
    - -
    -  - void - xdebug - (string $string) -
    -
    -
    -
    - - -
    -
    Variables
    - -
    - -
    - -
    - - - mixed - $attributes - = array() (line 1106) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $complexTypes - = array() (line 1107) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $complexTypeStack - = array() (line 1108) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $currentComplexType - = null (line 1109) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $currentElement - = null (line 1112) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $currentSimpleType - = null (line 1115) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $defaultNamespace - = array() (line 1124) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $depth - = 0 (line 1121) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $depth_array - = array() (line 1122) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $elements - = array() (line 1110) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $elementStack - = array() (line 1111) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $enclosingNamespaces - (line 1101) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $imports - = array() (line 1117) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $message - = array() (line 1123) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $parser - (line 1119) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $position - = 0 (line 1120) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $schema - = '' (line 1098) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $schemaInfo - = array() (line 1103) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $schemaTargetNamespace - = '' (line 1104) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $simpleTypes - = array() (line 1113) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $simpleTypeStack - = array() (line 1114) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $xml - = '' (line 1099) - -
    - - - - - - - -
    -

    Inherited Variables

    - -

    Inherited from nusoap_base

    -
    - - - nusoap_base::$charencoding
    -
    - - - nusoap_base::$debugLevel
    -
    - - - nusoap_base::$debug_str
    -
    - - - nusoap_base::$error_str
    -
    - - - nusoap_base::$namespaces
    -
    - - - nusoap_base::$revision
    -
    - - - nusoap_base::$soap_defencoding
    -
    - - - nusoap_base::$title
    -
    - - - nusoap_base::$typemap
    -
    - - - nusoap_base::$usedNamespaces
    -
    - - - nusoap_base::$version
    -
    - - - nusoap_base::$xmlEntities
    -
    - - - nusoap_base::$XMLSchemaVersion
    -
    -
    - -
    -
    - - -
    -
    Methods
    - -
    - - -
    - -
    - - Constructor nusoap_xmlschema (line 1134) -
    - - -

    constructor

    -
      -
    • access: public
    • -
    - -
    - nusoap_xmlschema - - nusoap_xmlschema - - ([string $schema = ''], [string $xml = ''], [string $namespaces = array()]) -
    - -
      -
    • - string - $schema: schema document URI
    • -
    • - string - $xml: xml document URI
    • -
    • - string - $namespaces: namespaces defined in enclosing XML
    • -
    - - -
    - -
    - -
    - - addComplexType (line 1985) -
    - - -

    adds a complex type to the schema

    -

    example: array

    addType( 'ArrayOfstring', 'complexType', 'array', '', 'SOAP-ENC:Array', array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'), 'xsd:string' );

    example: PHP associative array ( SOAP Struct )

    addType( 'SOAPStruct', 'complexType', 'struct', 'all', array('myVar'=> array('name'=>'myVar','type'=>'string') );

    - - -
    - void - - addComplexType - - (name $name, [typeClass $typeClass = 'complexType'], [phpType: $phpType = 'array'], [compositor $compositor = ''], [restrictionBase $restrictionBase = ''], [elements $elements = array()], [attrs $attrs = array()], [arrayType: $arrayType = '']) -
    - -
      -
    • - name - $name
    • -
    • - typeClass - $typeClass: (complexType|simpleType|attribute)
    • -
    • - phpType: - $phpType: currently supported are array and struct (php assoc array)
    • -
    • - compositor - $compositor: (all|sequence|choice)
    • -
    • - restrictionBase - $restrictionBase: namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
    • -
    • - elements - $elements: = array ( name = array(name=>'',type=>'') )
    • -
    • - attrs - $attrs: = array( array( 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType", "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]" ) )
    • -
    • - arrayType: - $arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
    • -
    - - -
    - -
    - -
    - - addElement (line 2033) -
    - - -

    adds an element to the schema

    - - -
    - void - - addElement - - (array $attrs) -
    - -
      -
    • - array - $attrs: attributes that must include name and type
    • -
    - - -
    - -
    - -
    - - addSimpleType (line 2013) -
    - - -

    adds a simple type to the schema

    - - -
    - void - - addSimpleType - - (string $name, [string $restrictionBase = ''], [string $typeClass = 'simpleType'], [string $phpType = 'scalar'], [array $enumeration = array()]) -
    - -
      -
    • - string - $name
    • -
    • - string - $restrictionBase: namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
    • -
    • - string - $typeClass: (should always be simpleType)
    • -
    • - string - $phpType: (should always be scalar)
    • -
    • - array - $enumeration: array of values
    • -
    - - -
    - -
    - -
    - - CreateTypeName (line 1240) -
    - - -

    gets a type name for an unnamed type

    -
      -
    • return: A type name for an unnamed type
    • -
    • access: private
    • -
    - -
    - string - - CreateTypeName - - (string $ename) -
    - -
      -
    • - string - $ename: Element name
    • -
    - - -
    - -
    - -
    - - getPHPType (line 1766) -
    - - -

    get the PHP type of a user defined type in the schema

    -

    PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays returns false if no type exists, or not w/ the given namespace else returns a string that is either a native php type, or 'struct'

    -
      -
    • deprecated:
    • -
    • access: public
    • -
    - -
    - mixed - - getPHPType - - (string $type, string $ns) -
    - -
      -
    • - string - $type: name of defined type
    • -
    • - string - $ns: namespace of type
    • -
    - - -
    - -
    - -
    - - getTypeDef (line 1799) -
    - - -

    returns an associative array of information about a given type returns false if no type exists by the given name

    -

    For a complexType typeDef = array( 'restrictionBase' => '', 'phpType' => '', 'compositor' => '(sequence|all)', 'elements' => array(), // refs to elements array 'attrs' => array() // refs to attributes array ... and so on (see addComplexType) )

    For simpleType or element, the array has different keys.

    - - -
    - mixed - - getTypeDef - - (string $type) -
    - -
      -
    • - string - $type
    • -
    - - -
    - -
    - -
    - - parseFile (line 1167) -
    - - -

    parse an XML file

    -
      -
    • access: public
    • -
    - -
    - boolean - - parseFile - - (string $xml, string $type) -
    - -
      -
    • - string - $xml: path/URL to XML file
    • -
    • - string - $type: (schema | xml)
    • -
    - - -
    - -
    - -
    - - parseString (line 1193) -
    - - -

    parse an XML string

    -
      -
    • access: private
    • -
    - -
    - void - - parseString - - (string $xml, string $type) -
    - -
      -
    • - string - $xml: path or URL
    • -
    • - string - $type: (schema|xml)
    • -
    - - -
    - -
    - -
    - - schemaCharacterData (line 1622) -
    - - -

    element content handler

    -
      -
    • access: private
    • -
    - -
    - void - - schemaCharacterData - - (string $parser, string $data) -
    - -
      -
    • - string - $parser: XML parser object
    • -
    • - string - $data: element content
    • -
    - - -
    - -
    - -
    - - schemaEndElement (line 1583) -
    - - -

    end-element handler

    -
      -
    • access: private
    • -
    - -
    - void - - schemaEndElement - - (string $parser, string $name) -
    - -
      -
    • - string - $parser: XML parser object
    • -
    • - string - $name: element name
    • -
    - - -
    - -
    - -
    - - schemaStartElement (line 1256) -
    - - -

    start-element handler

    -
      -
    • access: private
    • -
    - -
    - void - - schemaStartElement - - (string $parser, string $name, string $attrs) -
    - -
      -
    • - string - $parser: XML parser object
    • -
    • - string - $name: element name
    • -
    • - string - $attrs: associative array of attributes
    • -
    - - -
    - -
    - -
    - - serializeSchema (line 1632) -
    - - -

    serialize the schema

    -
      -
    • access: public
    • -
    - -
    - void - - serializeSchema - - () -
    - - - -
    - -
    - -
    - - serializeTypeDef (line 1878) -
    - - -

    returns a sample serialization of a given type, or false if no type by the given name

    -
      -
    • deprecated:
    • -
    • access: public
    • -
    - -
    - mixed - - serializeTypeDef - - (string $type) -
    - -
      -
    • - string - $type: name of type
    • -
    - - -
    - -
    - -
    - - typeToForm (line 1914) -
    - - -

    returns HTML form elements that allow a user to enter values for creating an instance of the given type.

    -
      -
    • deprecated:
    • -
    • access: public
    • -
    - -
    - string - - typeToForm - - (string $name, string $type) -
    - -
      -
    • - string - $name: name for type instance
    • -
    • - string - $type: name of type
    • -
    - - -
    - -
    - -
    - - xdebug (line 1750) -
    - - -

    adds debug data to the clas level debug string

    -
      -
    • access: private
    • -
    - -
    - void - - xdebug - - (string $string) -
    - -
      -
    • - string - $string: debug data
    • -
    - - -
    -

    Inherited Methods

    - - -

    Inherited From nusoap_base

    -
    -  - nusoap_base::nusoap_base()
    -  - nusoap_base::appendDebug()
    -  - nusoap_base::clearDebug()
    -  - nusoap_base::contractQname()
    -  - nusoap_base::debug()
    -  - nusoap_base::expandEntities()
    -  - nusoap_base::expandQname()
    -  - nusoap_base::formatDump()
    -  - nusoap_base::getDebug()
    -  - nusoap_base::getDebugAsXMLComment()
    -  - nusoap_base::getDebugLevel()
    -  - nusoap_base::getError()
    -  - nusoap_base::getGlobalDebugLevel()
    -  - nusoap_base::getLocalPart()
    -  - nusoap_base::getmicrotime()
    -  - nusoap_base::getNamespaceFromPrefix()
    -  - nusoap_base::getPrefix()
    -  - nusoap_base::getPrefixFromNamespace()
    -  - nusoap_base::isArraySimpleOrStruct()
    -  - nusoap_base::serializeEnvelope()
    -  - nusoap_base::serialize_val()
    -  - nusoap_base::setDebugLevel()
    -  - nusoap_base::setError()
    -  - nusoap_base::setGlobalDebugLevel()
    -  - nusoap_base::varDump()
    -  - nusoap_base::__toString()
    -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:04 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/nusoapservermime.html b/lib/nusoap/docs/docs/nusoap/nusoapservermime.html deleted file mode 100644 index 56fdb1ab4..000000000 --- a/lib/nusoap/docs/docs/nusoap/nusoapservermime.html +++ /dev/null @@ -1,374 +0,0 @@ - - - - - - Docs For Class nusoapservermime - - - - -
    -

     Class nusoapservermime

    - - -
    -
    Description
    - -
    - -

    nusoap_server_mime server supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.

    -
      -
    • version: $Id: nusoapmime.php,v 1.13 2010/04/26 20:15:08 snichol Exp $
    • -
    • author: Scott Nichol <snichol@users.sourceforge.net>
    • -
    • author: Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
    • -
    -

    - Located in /nusoapmime.php (line 498) -

    - - -
    nusoap_base
    -   |
    -   --nusoap_server
    -      |
    -      --nusoap_server_mime
    -         |
    -         --nusoapservermime
    - -
    -
    - - - - - - -
    -
    Variables
    - -
    -

    Inherited Variables

    - -

    Inherited from nusoap_server_mime

    -
    - - - nusoap_server_mime::$mimeContentType
    -
    - - - nusoap_server_mime::$requestAttachments
    -
    - - - nusoap_server_mime::$responseAttachments
    -
    -
    -

    Inherited from nusoap_server

    -
    - - - nusoap_server::$debug_flag
    -
    - - - nusoap_server::$decode_utf8
    -
    - - - nusoap_server::$document
    -
    - - - nusoap_server::$externalWSDLURL
    -
    - - - nusoap_server::$fault
    -
    - - - nusoap_server::$headers
    -
    - - - nusoap_server::$methodname
    -
    - - - nusoap_server::$methodparams
    -
    - - - nusoap_server::$methodreturn
    -
    - - - nusoap_server::$methodreturnisliteralxml
    -
    - - - nusoap_server::$methodURI
    -
    - - - nusoap_server::$operations
    -
    - - - nusoap_server::$outgoing_headers
    -
    - - - nusoap_server::$request
    -
    - - - nusoap_server::$requestHeader
    -
    - - - nusoap_server::$requestHeaders
    -
    - - - nusoap_server::$requestSOAP
    -
    - - - nusoap_server::$response
    -
    - - - nusoap_server::$responseHeaders
    -
    - - - nusoap_server::$responseSOAP
    -
    - - - nusoap_server::$result
    -
    - - - nusoap_server::$SOAPAction
    -
    - - - nusoap_server::$wsdl
    -
    - - - nusoap_server::$xml_encoding
    -
    -
    -

    Inherited from nusoap_base

    -
    - - - nusoap_base::$charencoding
    -
    - - - nusoap_base::$debugLevel
    -
    - - - nusoap_base::$debug_str
    -
    - - - nusoap_base::$error_str
    -
    - - - nusoap_base::$namespaces
    -
    - - - nusoap_base::$revision
    -
    - - - nusoap_base::$soap_defencoding
    -
    - - - nusoap_base::$title
    -
    - - - nusoap_base::$typemap
    -
    - - - nusoap_base::$usedNamespaces
    -
    - - - nusoap_base::$version
    -
    - - - nusoap_base::$xmlEntities
    -
    - - - nusoap_base::$XMLSchemaVersion
    -
    -
    - -
    -
    - - -
    -
    Methods
    - -
    - -

    Inherited Methods

    - - -

    Inherited From nusoap_server_mime

    -
    -  - nusoap_server_mime::addAttachment()
    -  - nusoap_server_mime::clearAttachments()
    -  - nusoap_server_mime::getAttachments()
    -  - nusoap_server_mime::getHTTPBody()
    -  - nusoap_server_mime::getHTTPContentType()
    -  - nusoap_server_mime::getHTTPContentTypeCharset()
    -  - nusoap_server_mime::parseRequest()
    -
    - -

    Inherited From nusoap_server

    -
    -  - nusoap_server::nusoap_server()
    -  - nusoap_server::add_to_map()
    -  - nusoap_server::configureWSDL()
    -  - nusoap_server::fault()
    -  - nusoap_server::getHTTPBody()
    -  - nusoap_server::getHTTPContentType()
    -  - nusoap_server::getHTTPContentTypeCharset()
    -  - nusoap_server::invoke_method()
    -  - nusoap_server::parseRequest()
    -  - nusoap_server::parse_http_headers()
    -  - nusoap_server::parse_request()
    -  - nusoap_server::register()
    -  - nusoap_server::send_response()
    -  - nusoap_server::serialize_return()
    -  - nusoap_server::service()
    -  - nusoap_server::verify_method()
    -
    - -

    Inherited From nusoap_base

    -
    -  - nusoap_base::nusoap_base()
    -  - nusoap_base::appendDebug()
    -  - nusoap_base::clearDebug()
    -  - nusoap_base::contractQname()
    -  - nusoap_base::debug()
    -  - nusoap_base::expandEntities()
    -  - nusoap_base::expandQname()
    -  - nusoap_base::formatDump()
    -  - nusoap_base::getDebug()
    -  - nusoap_base::getDebugAsXMLComment()
    -  - nusoap_base::getDebugLevel()
    -  - nusoap_base::getError()
    -  - nusoap_base::getGlobalDebugLevel()
    -  - nusoap_base::getLocalPart()
    -  - nusoap_base::getmicrotime()
    -  - nusoap_base::getNamespaceFromPrefix()
    -  - nusoap_base::getPrefix()
    -  - nusoap_base::getPrefixFromNamespace()
    -  - nusoap_base::isArraySimpleOrStruct()
    -  - nusoap_base::serializeEnvelope()
    -  - nusoap_base::serialize_val()
    -  - nusoap_base::setDebugLevel()
    -  - nusoap_base::setError()
    -  - nusoap_base::setGlobalDebugLevel()
    -  - nusoap_base::varDump()
    -  - nusoap_base::__toString()
    -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:09 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/soap_fault.html b/lib/nusoap/docs/docs/nusoap/soap_fault.html deleted file mode 100644 index 59279361f..000000000 --- a/lib/nusoap/docs/docs/nusoap/soap_fault.html +++ /dev/null @@ -1,230 +0,0 @@ - - - - - - Docs For Class soap_fault - - - - -
    -

     Class soap_fault

    - - -
    -
    Description
    - -
    - -

    Backward compatibility

    -
      -
    • version: $Id: soap_fault.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    • -
    • author: Dietrich Ayala <dietrich@ganx4.com>
    • -
    -

    - Located in /nusoap.php (line 1079) -

    - - -
    nusoap_base
    -   |
    -   --nusoap_fault
    -      |
    -      --soap_fault
    - -
    -
    - - - - - - - - - - - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:06 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/soap_parser.html b/lib/nusoap/docs/docs/nusoap/soap_parser.html deleted file mode 100644 index 042d90f19..000000000 --- a/lib/nusoap/docs/docs/nusoap/soap_parser.html +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - Docs For Class soap_parser - - - - -
    -

     Class soap_parser

    - - -
    -
    Description
    - -
    - -

    Backward compatibility

    - -

    - Located in /nusoap.php (line 7070) -

    - - -
    nusoap_base
    -   |
    -   --nusoap_parser
    -      |
    -      --soap_parser
    - -
    -
    - - - - - - -
    -
    Variables
    - - -
    - - - - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:06 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/soap_server.html b/lib/nusoap/docs/docs/nusoap/soap_server.html deleted file mode 100644 index 6c996d0f3..000000000 --- a/lib/nusoap/docs/docs/nusoap/soap_server.html +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - Docs For Class soap_server - - - - -
    -

     Class soap_server

    - - -
    -
    Description
    - -
    - -

    Backward compatibility

    - -

    - Located in /nusoap.php (line 4580) -

    - - -
    nusoap_base
    -   |
    -   --nusoap_server
    -      |
    -      --soap_server
    - -
    -
    - - - - - - - - - -
    -
    Methods
    - -
    - -

    Inherited Methods

    - - -

    Inherited From nusoap_server

    -
    -  - nusoap_server::nusoap_server()
    -  - nusoap_server::add_to_map()
    -  - nusoap_server::configureWSDL()
    -  - nusoap_server::fault()
    -  - nusoap_server::getHTTPBody()
    -  - nusoap_server::getHTTPContentType()
    -  - nusoap_server::getHTTPContentTypeCharset()
    -  - nusoap_server::invoke_method()
    -  - nusoap_server::parseRequest()
    -  - nusoap_server::parse_http_headers()
    -  - nusoap_server::parse_request()
    -  - nusoap_server::register()
    -  - nusoap_server::send_response()
    -  - nusoap_server::serialize_return()
    -  - nusoap_server::service()
    -  - nusoap_server::verify_method()
    -
    - -

    Inherited From nusoap_base

    -
    -  - nusoap_base::nusoap_base()
    -  - nusoap_base::appendDebug()
    -  - nusoap_base::clearDebug()
    -  - nusoap_base::contractQname()
    -  - nusoap_base::debug()
    -  - nusoap_base::expandEntities()
    -  - nusoap_base::expandQname()
    -  - nusoap_base::formatDump()
    -  - nusoap_base::getDebug()
    -  - nusoap_base::getDebugAsXMLComment()
    -  - nusoap_base::getDebugLevel()
    -  - nusoap_base::getError()
    -  - nusoap_base::getGlobalDebugLevel()
    -  - nusoap_base::getLocalPart()
    -  - nusoap_base::getmicrotime()
    -  - nusoap_base::getNamespaceFromPrefix()
    -  - nusoap_base::getPrefix()
    -  - nusoap_base::getPrefixFromNamespace()
    -  - nusoap_base::isArraySimpleOrStruct()
    -  - nusoap_base::serializeEnvelope()
    -  - nusoap_base::serialize_val()
    -  - nusoap_base::setDebugLevel()
    -  - nusoap_base::setError()
    -  - nusoap_base::setGlobalDebugLevel()
    -  - nusoap_base::varDump()
    -  - nusoap_base::__toString()
    -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:06 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/soap_transport_http.html b/lib/nusoap/docs/docs/nusoap/soap_transport_http.html deleted file mode 100644 index f6fb4cd0e..000000000 --- a/lib/nusoap/docs/docs/nusoap/soap_transport_http.html +++ /dev/null @@ -1,1765 +0,0 @@ - - - - - - Docs For Class soap_transport_http - - - - -
    -

     Class soap_transport_http

    - - -
    -
    Description
    - -
    - -

    transport class for sending/receiving data via HTTP and HTTPS NOTE: PHP must be compiled with the CURL extension for HTTPS support

    - -

    - Located in /nusoap.php (line 2168) -

    - - -
    nusoap_base
    -   |
    -   --soap_transport_http
    - -
    -
    - - - - -
    -
    Variable Summary
    - -
    -
    -
    -  - mixed - $authtype -
    -
    -  - mixed - $certRequest -
    -
    -  - mixed - $ch -
    -
    -  - mixed - $ch_options -
    -
    -  - mixed - $digestRequest -
    -
    -  - mixed - $digest_uri -
    -
    -  - mixed - $encoding -
    -
    -  - mixed - $host -
    -
    -  - mixed - $incoming_cookies -
    -
    -  - mixed - $incoming_headers -
    -
    -  - mixed - $incoming_payload -
    -
    -  - mixed - $outgoing_headers -
    -
    -  - mixed - $outgoing_payload -
    -
    -  - mixed - $password -
    -
    -  - mixed - $path -
    -
    -  - mixed - $persistentConnection -
    -
    -  - mixed - $port -
    -
    -  - mixed - $protocol_version -
    -
    -  - mixed - $proxy -
    -
    -  - mixed - $request_method -
    -
    -  - mixed - $response_status_line -
    -
    -  - mixed - $scheme -
    -
    -  - mixed - $uri -
    -
    -  - mixed - $url -
    -
    -  - mixed - $username -
    -
    -  - mixed - $useSOAPAction -
    -
    -  - mixed - $use_curl -
    -
    -
    -
    - - -
    -
    Method Summary
    - -
    -
    - -
    -  - soap_transport_http - soap_transport_http - (string $url, [array $curl_options = NULL], [boolean $use_curl = false]) -
    - -
    -  - void - buildPayload - (string $data, [string $cookie_str = '']) -
    - -
    -  - boolean - connect - (mixed $connection_timeout, [integer $response_timeout = 30], integer $timeout) -
    - -
    -  - string - decodeChunked - (string $buffer, string $lb) -
    - -
    -  - string - getCookiesForRequest - (array $cookies, [boolean $secure = false]) -
    - -
    -  - string - getResponse - () -
    - -
    -  - string - io_method - () -
    - -
    -  - boolean - isSkippableCurlHeader - (string &$data) -
    - -
    -  - array - parseCookie - (string $cookie_str) -
    - -
    -  - string - send - (string $data, integer $timeout, [integer $response_timeout = 30], [array $cookies = NULL]) -
    - -
    -  - string - sendHTTPS - (string $data, integer $timeout, [integer $response_timeout = 30], array $cookies) -
    - -
    -  - boolean - sendRequest - (string $data, [array $cookies = NULL]) -
    - -
    -  - void - setContentType - (string $type, [mixed $charset = false]) -
    - -
    -  - void - setCredentials - (string $username, string $password, [string $authtype = 'basic'], [array $digestRequest = array()], [array $certRequest = array()]) -
    - -
    -  - void - setCurlOption - (mixed $option, mixed $value) -
    - -
    -  - void - setEncoding - ([string $enc = 'gzip, deflate']) -
    - -
    -  - void - setHeader - (string $name, string $value) -
    - -
    -  - void - setProxy - (string $proxyhost, string $proxyport, [string $proxyusername = ''], [string $proxypassword = ''], [string $proxyauthtype = 'basic']) -
    - -
    -  - void - setSOAPAction - (string $soapaction) -
    - -
    -  - void - setURL - (string $url) -
    - -
    -  - void - unsetHeader - (string $name) -
    - -
    -  - boolean - usePersistentConnection - () -
    -
    -
    -
    - - -
    -
    Variables
    - -
    - -
    - -
    - - - mixed - $authtype - = '' (line 2194) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $certRequest - = array() (line 2196) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $ch - = false (line 2188) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $ch_options - = array() (line 2189) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $digestRequest - = array() (line 2195) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $digest_uri - = '' (line 2172) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $encoding - = '' (line 2179) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $host - = '' (line 2174) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $incoming_cookies - = array() (line 2182) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $incoming_headers - = array() (line 2181) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $incoming_payload - = '' (line 2184) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $outgoing_headers - = array() (line 2180) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $outgoing_payload - = '' (line 2183) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $password - = '' (line 2193) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $path - = '' (line 2176) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $persistentConnection - = false (line 2187) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $port - = '' (line 2175) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $protocol_version - = '1.0' (line 2178) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $proxy - = null (line 2191) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $request_method - = 'POST' (line 2177) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $response_status_line - (line 2185) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $scheme - = '' (line 2173) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $uri - = '' (line 2171) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $url - = '' (line 2170) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $username - = '' (line 2192) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $useSOAPAction - = true (line 2186) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $use_curl - = false (line 2190) - -
    - - - - - - - -
    -

    Inherited Variables

    - -

    Inherited from nusoap_base

    -
    - - - nusoap_base::$charencoding
    -
    - - - nusoap_base::$debugLevel
    -
    - - - nusoap_base::$debug_str
    -
    - - - nusoap_base::$error_str
    -
    - - - nusoap_base::$namespaces
    -
    - - - nusoap_base::$revision
    -
    - - - nusoap_base::$soap_defencoding
    -
    - - - nusoap_base::$title
    -
    - - - nusoap_base::$typemap
    -
    - - - nusoap_base::$usedNamespaces
    -
    - - - nusoap_base::$version
    -
    - - - nusoap_base::$xmlEntities
    -
    - - - nusoap_base::$XMLSchemaVersion
    -
    -
    - -
    -
    - - -
    -
    Methods
    - -
    - - -
    - -
    - - Constructor soap_transport_http (line 2213) -
    - - -

    constructor

    -
      -
    • access: public
    • -
    - -
    - soap_transport_http - - soap_transport_http - - (string $url, [array $curl_options = NULL], [boolean $use_curl = false]) -
    - -
      -
    • - string - $url: The URL to which to connect
    • -
    • - array - $curl_options: User-specified cURL options
    • -
    • - boolean - $use_curl: Whether to try to force cURL use
    • -
    - - -
    - -
    - -
    - - buildPayload (line 2841) -
    - - -

    Writes the payload, including HTTP headers, to $this->outgoing_payload.

    -
      -
    • access: private
    • -
    - -
    - void - - buildPayload - - (string $data, [string $cookie_str = '']) -
    - -
      -
    • - string - $data: HTTP body
    • -
    • - string - $cookie_str: data for HTTP Cookie header
    • -
    - - -
    - -
    - -
    - - connect (line 2330) -
    - - -

    establish an HTTP connection

    -
      -
    • return: true if connected, false if not
    • -
    • access: private
    • -
    - -
    - boolean - - connect - - (mixed $connection_timeout, [integer $response_timeout = 30], integer $timeout) -
    - -
      -
    • - integer - $timeout: set connection timeout in seconds
    • -
    • - integer - $response_timeout: set response timeout in seconds
    • -
    - - -
    - -
    - -
    - - decodeChunked (line 2784) -
    - - -

    decode a string that is encoded w/ "chunked' transfer encoding as defined in RFC2068 19.4.6

    -
      -
    • deprecated:
    • -
    • access: public
    • -
    - -
    - string - - decodeChunked - - (string $buffer, string $lb) -
    - -
      -
    • - string - $buffer
    • -
    • - string - $lb
    • -
    - - -
    - -
    - -
    - - getCookiesForRequest (line 3419) -
    - - -

    sort out cookies for the current request

    -
      -
    • return: for Cookie-HTTP-Header
    • -
    • access: private
    • -
    - -
    - string - - getCookiesForRequest - - (array $cookies, [boolean $secure = false]) -
    - -
      -
    • - array - $cookies: array with all cookies
    • -
    • - boolean - $secure: is the send-content secure or not?
    • -
    - - -
    - -
    - -
    - - getResponse (line 2947) -
    - - -

    gets the SOAP response via HTTP[S]

    -
      -
    • return: the response (also sets member variables like incoming_payload)
    • -
    • access: private
    • -
    - -
    - string - - getResponse - - () -
    - - - -
    - -
    - -
    - - io_method (line 2314) -
    - - -

    gets the I/O method to use

    -
      -
    • return: I/O method to use (socket|curl|unknown)
    • -
    • access: private
    • -
    - -
    - string - - io_method - - () -
    - - - -
    - -
    - -
    - - isSkippableCurlHeader (line 2757) -
    - - -

    Test if the given string starts with a header that is to be skipped.

    -

    Skippable headers result from chunked transfer and proxy requests.

    -
      -
    • return: Whether a skippable header was found.
    • -
    • access: private
    • -
    - -
    - boolean - - isSkippableCurlHeader - - (string &$data) -
    - -
      -
    • - string - $data: The string to check.
    • -
    - - -
    - -
    - -
    - - parseCookie (line 3355) -
    - - -

    parse an incoming Cookie into it's parts

    -
      -
    • return: with data of that cookie
    • -
    • access: private
    • -
    - -
    - array - - parseCookie - - (string $cookie_str) -
    - -
      -
    • - string - $cookie_str: content of cookie
    • -
    - - -
    - -
    - -
    - - send (line 2566) -
    - - -

    sends the SOAP request and gets the SOAP response via HTTP[S]

    -
      -
    • return: data
    • -
    • access: public
    • -
    - -
    - string - - send - - (string $data, integer $timeout, [integer $response_timeout = 30], [array $cookies = NULL]) -
    - -
      -
    • - string - $data: message data
    • -
    • - integer - $timeout: set connection timeout in seconds
    • -
    • - integer - $response_timeout: set response timeout in seconds
    • -
    • - array - $cookies: cookies to send
    • -
    - - -
    - -
    - -
    - - sendHTTPS (line 2607) -
    - - -

    sends the SOAP request and gets the SOAP response via HTTPS using CURL

    -
      -
    • return: data
    • -
    • deprecated:
    • -
    • access: public
    • -
    - -
    - string - - sendHTTPS - - (string $data, integer $timeout, [integer $response_timeout = 30], array $cookies) -
    - -
      -
    • - string - $data: message data
    • -
    • - integer - $timeout: set connection timeout in seconds
    • -
    • - integer - $response_timeout: set response timeout in seconds
    • -
    • - array - $cookies: cookies to send
    • -
    - - -
    - -
    - -
    - - sendRequest (line 2890) -
    - - -

    sends the SOAP request via HTTP[S]

    -
      -
    • return: true if OK, false if problem
    • -
    • access: private
    • -
    - -
    - boolean - - sendRequest - - (string $data, [array $cookies = NULL]) -
    - -
      -
    • - string - $data: message data
    • -
    • - array - $cookies: cookies to send
    • -
    - - -
    - -
    - -
    - - setContentType (line 3325) -
    - - -

    sets the content-type for the SOAP message to be sent

    -
      -
    • access: public
    • -
    - -
    - void - - setContentType - - (string $type, [mixed $charset = false]) -
    - -
      -
    • - string - $type: the content type, MIME style
    • -
    • - mixed - $charset: character set used for encoding (or false)
    • -
    - - -
    - -
    - -
    - - setCredentials (line 2621) -
    - - -

    if authenticating, set user credentials here

    -
      -
    • access: public
    • -
    - -
    - void - - setCredentials - - (string $username, string $password, [string $authtype = 'basic'], [array $digestRequest = array()], [array $certRequest = array()]) -
    - -
      -
    • - string - $username
    • -
    • - string - $password
    • -
    • - string - $authtype: (basic|digest|certificate|ntlm)
    • -
    • - array - $digestRequest: (keys must be nonce, nc, realm, qop)
    • -
    • - array - $certRequest: (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
    • -
    - - -
    - -
    - -
    - - setCurlOption (line 2233) -
    - - -

    sets a cURL option

    -
      -
    • access: private
    • -
    - -
    - void - - setCurlOption - - (mixed $option, mixed $value) -
    - -
      -
    • - mixed - $option: The cURL option (always integer?)
    • -
    • - mixed - $value: The cURL option value
    • -
    - - -
    - -
    - -
    - - setEncoding (line 2705) -
    - - -

    use http encoding

    -
      -
    • access: public
    • -
    - -
    - void - - setEncoding - - ([string $enc = 'gzip, deflate']) -
    - -
      -
    • - string - $enc: encoding style. supported values: gzip, deflate, or both
    • -
    - - -
    - -
    - -
    - - setHeader (line 2246) -
    - - -

    sets an HTTP header

    -
      -
    • access: private
    • -
    - -
    - void - - setHeader - - (string $name, string $value) -
    - -
      -
    • - string - $name: The name of the header
    • -
    • - string - $value: The value of the header
    • -
    - - -
    - -
    - -
    - - setProxy (line 2729) -
    - - -

    set proxy info here

    -
      -
    • access: public
    • -
    - -
    - void - - setProxy - - (string $proxyhost, string $proxyport, [string $proxyusername = ''], [string $proxypassword = ''], [string $proxyauthtype = 'basic']) -
    - -
      -
    • - string - $proxyhost: use an empty string to remove proxy
    • -
    • - string - $proxyport
    • -
    • - string - $proxyusername
    • -
    • - string - $proxypassword
    • -
    • - string - $proxyauthtype: (basic|ntlm)
    • -
    - - -
    - -
    - -
    - - setSOAPAction (line 2695) -
    - - -

    set the soapaction value

    -
      -
    • access: public
    • -
    - -
    - void - - setSOAPAction - - (string $soapaction) -
    - -
      -
    • - string - $soapaction
    • -
    - - -
    - -
    - -
    - - setURL (line 2270) -
    - - -

    sets the URL to which to connect

    -
      -
    • access: private
    • -
    - -
    - void - - setURL - - (string $url) -
    - -
      -
    • - string - $url: The URL to which to connect
    • -
    - - -
    - -
    - -
    - - unsetHeader (line 2257) -
    - - -

    unsets an HTTP header

    -
      -
    • access: private
    • -
    - -
    - void - - unsetHeader - - (string $name) -
    - -
      -
    • - string - $name: The name of the header
    • -
    - - -
    - -
    - -
    - - usePersistentConnection (line 3335) -
    - - -

    specifies that an HTTP persistent connection should be used

    -
      -
    • return: whether the request was honored by this method.
    • -
    • access: public
    • -
    - -
    - boolean - - usePersistentConnection - - () -
    - - - -
    -

    Inherited Methods

    - - -

    Inherited From nusoap_base

    -
    -  - nusoap_base::nusoap_base()
    -  - nusoap_base::appendDebug()
    -  - nusoap_base::clearDebug()
    -  - nusoap_base::contractQname()
    -  - nusoap_base::debug()
    -  - nusoap_base::expandEntities()
    -  - nusoap_base::expandQname()
    -  - nusoap_base::formatDump()
    -  - nusoap_base::getDebug()
    -  - nusoap_base::getDebugAsXMLComment()
    -  - nusoap_base::getDebugLevel()
    -  - nusoap_base::getError()
    -  - nusoap_base::getGlobalDebugLevel()
    -  - nusoap_base::getLocalPart()
    -  - nusoap_base::getmicrotime()
    -  - nusoap_base::getNamespaceFromPrefix()
    -  - nusoap_base::getPrefix()
    -  - nusoap_base::getPrefixFromNamespace()
    -  - nusoap_base::isArraySimpleOrStruct()
    -  - nusoap_base::serializeEnvelope()
    -  - nusoap_base::serialize_val()
    -  - nusoap_base::setDebugLevel()
    -  - nusoap_base::setError()
    -  - nusoap_base::setGlobalDebugLevel()
    -  - nusoap_base::varDump()
    -  - nusoap_base::__toString()
    -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:06 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/soapclient.html b/lib/nusoap/docs/docs/nusoap/soapclient.html deleted file mode 100644 index b10bf5d38..000000000 --- a/lib/nusoap/docs/docs/nusoap/soapclient.html +++ /dev/null @@ -1,411 +0,0 @@ - - - - - - Docs For Class soapclient - - - - -
    -

     Class soapclient

    - - -
    -
    Description
    - -
    - -

    For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.

    - -

    - Located in /nusoap.php (line 8055) -

    - - -
    nusoap_base
    -   |
    -   --nusoap_client
    -      |
    -      --soapclient
    - -
    -
    - - - - - - -
    -
    Variables
    - -
    -

    Inherited Variables

    - -

    Inherited from nusoap_client

    -
    - - - nusoap_client::$authtype
    -
    - - - nusoap_client::$bindingType
    -
    - - - nusoap_client::$certRequest
    -
    - - - nusoap_client::$cookies
    -
    - - - nusoap_client::$curl_options
    -
    - - - nusoap_client::$decode_utf8
    -
    - - - nusoap_client::$defaultRpcParams
    -
    - - - nusoap_client::$document
    -
    - - - nusoap_client::$endpoint
    -
    - - - nusoap_client::$endpointType
    -
    - - - nusoap_client::$fault
    -
    - - - nusoap_client::$faultcode
    -
    - - - nusoap_client::$faultdetail
    -
    - - - nusoap_client::$faultstring
    -
    - - - nusoap_client::$forceEndpoint
    -
    - - - nusoap_client::$http_encoding
    -
    - - - nusoap_client::$operations
    -
    - - - nusoap_client::$password
    -
    - - - nusoap_client::$persistentConnection
    -
    - - - nusoap_client::$portName
    -
    - - - nusoap_client::$proxyhost
    -
    - - - nusoap_client::$proxypassword
    -
    - - - nusoap_client::$proxyport
    -
    - - - nusoap_client::$proxyusername
    -
    - - - nusoap_client::$request
    -
    - - - nusoap_client::$requestHeaders
    -
    - - - nusoap_client::$response
    -
    - - - nusoap_client::$responseData
    -
    - - - nusoap_client::$responseHeader
    -
    - - - nusoap_client::$responseHeaders
    -
    - - - nusoap_client::$response_timeout
    -
    - - - nusoap_client::$timeout
    -
    - - - nusoap_client::$username
    -
    - - - nusoap_client::$use_curl
    -
    - - - nusoap_client::$xml_encoding
    -
    -
    -

    Inherited from nusoap_base

    -
    - - - nusoap_base::$charencoding
    -
    - - - nusoap_base::$debugLevel
    -
    - - - nusoap_base::$debug_str
    -
    - - - nusoap_base::$error_str
    -
    - - - nusoap_base::$namespaces
    -
    - - - nusoap_base::$revision
    -
    - - - nusoap_base::$soap_defencoding
    -
    - - - nusoap_base::$title
    -
    - - - nusoap_base::$typemap
    -
    - - - nusoap_base::$usedNamespaces
    -
    - - - nusoap_base::$version
    -
    - - - nusoap_base::$xmlEntities
    -
    - - - nusoap_base::$XMLSchemaVersion
    -
    -
    - -
    -
    - - -
    -
    Methods
    - -
    - -

    Inherited Methods

    - - -

    Inherited From nusoap_client

    -
    -  - nusoap_client::nusoap_client()
    -  - nusoap_client::call()
    -  - nusoap_client::checkCookies()
    -  - nusoap_client::checkWSDL()
    -  - nusoap_client::decodeUTF8()
    -  - nusoap_client::getCookies()
    -  - nusoap_client::getDefaultRpcParams()
    -  - nusoap_client::getHeader()
    -  - nusoap_client::getHeaders()
    -  - nusoap_client::getHTTPBody()
    -  - nusoap_client::getHTTPContentType()
    -  - nusoap_client::getHTTPContentTypeCharset()
    -  - nusoap_client::getOperationData()
    -  - nusoap_client::getProxy()
    -  - nusoap_client::getProxyClassCode()
    -  - nusoap_client::loadWSDL()
    -  - nusoap_client::parseResponse()
    -  - nusoap_client::send()
    -  - nusoap_client::setCookie()
    -  - nusoap_client::setCredentials()
    -  - nusoap_client::setCurlOption()
    -  - nusoap_client::setDefaultRpcParams()
    -  - nusoap_client::setEndpoint()
    -  - nusoap_client::setHeaders()
    -  - nusoap_client::setHTTPEncoding()
    -  - nusoap_client::setHTTPProxy()
    -  - nusoap_client::setUseCURL()
    -  - nusoap_client::UpdateCookies()
    -  - nusoap_client::useHTTPPersistentConnection()
    -  - nusoap_client::_getProxyClassCode()
    -
    - -

    Inherited From nusoap_base

    -
    -  - nusoap_base::nusoap_base()
    -  - nusoap_base::appendDebug()
    -  - nusoap_base::clearDebug()
    -  - nusoap_base::contractQname()
    -  - nusoap_base::debug()
    -  - nusoap_base::expandEntities()
    -  - nusoap_base::expandQname()
    -  - nusoap_base::formatDump()
    -  - nusoap_base::getDebug()
    -  - nusoap_base::getDebugAsXMLComment()
    -  - nusoap_base::getDebugLevel()
    -  - nusoap_base::getError()
    -  - nusoap_base::getGlobalDebugLevel()
    -  - nusoap_base::getLocalPart()
    -  - nusoap_base::getmicrotime()
    -  - nusoap_base::getNamespaceFromPrefix()
    -  - nusoap_base::getPrefix()
    -  - nusoap_base::getPrefixFromNamespace()
    -  - nusoap_base::isArraySimpleOrStruct()
    -  - nusoap_base::serializeEnvelope()
    -  - nusoap_base::serialize_val()
    -  - nusoap_base::setDebugLevel()
    -  - nusoap_base::setError()
    -  - nusoap_base::setGlobalDebugLevel()
    -  - nusoap_base::varDump()
    -  - nusoap_base::__toString()
    -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:05 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/soapclientmime.html b/lib/nusoap/docs/docs/nusoap/soapclientmime.html deleted file mode 100644 index 2869e5260..000000000 --- a/lib/nusoap/docs/docs/nusoap/soapclientmime.html +++ /dev/null @@ -1,446 +0,0 @@ - - - - - - Docs For Class soapclientmime - - - - -
    -

     Class soapclientmime

    - - -
    -
    Description
    - -
    - -

    nusoap_client_mime client supporting MIME attachments defined at http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.

    -
      -
    • version: $Id: soapclientmime.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    • -
    • author: Scott Nichol <snichol@users.sourceforge.net>
    • -
    • author: Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
    • -
    -

    - Located in /nusoapmime.php (line 271) -

    - - -
    nusoap_base
    -   |
    -   --nusoap_client
    -      |
    -      --nusoap_client_mime
    -         |
    -         --soapclientmime
    - -
    -
    - - - - - - -
    -
    Variables
    - -
    -

    Inherited Variables

    - -

    Inherited from nusoap_client_mime

    -
    - - - nusoap_client_mime::$mimeContentType
    -
    - - - nusoap_client_mime::$requestAttachments
    -
    - - - nusoap_client_mime::$responseAttachments
    -
    -
    -

    Inherited from nusoap_client

    -
    - - - nusoap_client::$authtype
    -
    - - - nusoap_client::$bindingType
    -
    - - - nusoap_client::$certRequest
    -
    - - - nusoap_client::$cookies
    -
    - - - nusoap_client::$curl_options
    -
    - - - nusoap_client::$decode_utf8
    -
    - - - nusoap_client::$defaultRpcParams
    -
    - - - nusoap_client::$document
    -
    - - - nusoap_client::$endpoint
    -
    - - - nusoap_client::$endpointType
    -
    - - - nusoap_client::$fault
    -
    - - - nusoap_client::$faultcode
    -
    - - - nusoap_client::$faultdetail
    -
    - - - nusoap_client::$faultstring
    -
    - - - nusoap_client::$forceEndpoint
    -
    - - - nusoap_client::$http_encoding
    -
    - - - nusoap_client::$operations
    -
    - - - nusoap_client::$password
    -
    - - - nusoap_client::$persistentConnection
    -
    - - - nusoap_client::$portName
    -
    - - - nusoap_client::$proxyhost
    -
    - - - nusoap_client::$proxypassword
    -
    - - - nusoap_client::$proxyport
    -
    - - - nusoap_client::$proxyusername
    -
    - - - nusoap_client::$request
    -
    - - - nusoap_client::$requestHeaders
    -
    - - - nusoap_client::$response
    -
    - - - nusoap_client::$responseData
    -
    - - - nusoap_client::$responseHeader
    -
    - - - nusoap_client::$responseHeaders
    -
    - - - nusoap_client::$response_timeout
    -
    - - - nusoap_client::$timeout
    -
    - - - nusoap_client::$username
    -
    - - - nusoap_client::$use_curl
    -
    - - - nusoap_client::$xml_encoding
    -
    -
    -

    Inherited from nusoap_base

    -
    - - - nusoap_base::$charencoding
    -
    - - - nusoap_base::$debugLevel
    -
    - - - nusoap_base::$debug_str
    -
    - - - nusoap_base::$error_str
    -
    - - - nusoap_base::$namespaces
    -
    - - - nusoap_base::$revision
    -
    - - - nusoap_base::$soap_defencoding
    -
    - - - nusoap_base::$title
    -
    - - - nusoap_base::$typemap
    -
    - - - nusoap_base::$usedNamespaces
    -
    - - - nusoap_base::$version
    -
    - - - nusoap_base::$xmlEntities
    -
    - - - nusoap_base::$XMLSchemaVersion
    -
    -
    - -
    -
    - - -
    -
    Methods
    - -
    - -

    Inherited Methods

    - - -

    Inherited From nusoap_client_mime

    -
    -  - nusoap_client_mime::addAttachment()
    -  - nusoap_client_mime::clearAttachments()
    -  - nusoap_client_mime::getAttachments()
    -  - nusoap_client_mime::getHTTPBody()
    -  - nusoap_client_mime::getHTTPContentType()
    -  - nusoap_client_mime::getHTTPContentTypeCharset()
    -  - nusoap_client_mime::parseResponse()
    -
    - -

    Inherited From nusoap_client

    -
    -  - nusoap_client::nusoap_client()
    -  - nusoap_client::call()
    -  - nusoap_client::checkCookies()
    -  - nusoap_client::checkWSDL()
    -  - nusoap_client::decodeUTF8()
    -  - nusoap_client::getCookies()
    -  - nusoap_client::getDefaultRpcParams()
    -  - nusoap_client::getHeader()
    -  - nusoap_client::getHeaders()
    -  - nusoap_client::getHTTPBody()
    -  - nusoap_client::getHTTPContentType()
    -  - nusoap_client::getHTTPContentTypeCharset()
    -  - nusoap_client::getOperationData()
    -  - nusoap_client::getProxy()
    -  - nusoap_client::getProxyClassCode()
    -  - nusoap_client::loadWSDL()
    -  - nusoap_client::parseResponse()
    -  - nusoap_client::send()
    -  - nusoap_client::setCookie()
    -  - nusoap_client::setCredentials()
    -  - nusoap_client::setCurlOption()
    -  - nusoap_client::setDefaultRpcParams()
    -  - nusoap_client::setEndpoint()
    -  - nusoap_client::setHeaders()
    -  - nusoap_client::setHTTPEncoding()
    -  - nusoap_client::setHTTPProxy()
    -  - nusoap_client::setUseCURL()
    -  - nusoap_client::UpdateCookies()
    -  - nusoap_client::useHTTPPersistentConnection()
    -  - nusoap_client::_getProxyClassCode()
    -
    - -

    Inherited From nusoap_base

    -
    -  - nusoap_base::nusoap_base()
    -  - nusoap_base::appendDebug()
    -  - nusoap_base::clearDebug()
    -  - nusoap_base::contractQname()
    -  - nusoap_base::debug()
    -  - nusoap_base::expandEntities()
    -  - nusoap_base::expandQname()
    -  - nusoap_base::formatDump()
    -  - nusoap_base::getDebug()
    -  - nusoap_base::getDebugAsXMLComment()
    -  - nusoap_base::getDebugLevel()
    -  - nusoap_base::getError()
    -  - nusoap_base::getGlobalDebugLevel()
    -  - nusoap_base::getLocalPart()
    -  - nusoap_base::getmicrotime()
    -  - nusoap_base::getNamespaceFromPrefix()
    -  - nusoap_base::getPrefix()
    -  - nusoap_base::getPrefixFromNamespace()
    -  - nusoap_base::isArraySimpleOrStruct()
    -  - nusoap_base::serializeEnvelope()
    -  - nusoap_base::serialize_val()
    -  - nusoap_base::setDebugLevel()
    -  - nusoap_base::setError()
    -  - nusoap_base::setGlobalDebugLevel()
    -  - nusoap_base::varDump()
    -  - nusoap_base::__toString()
    -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:11 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/soapval.html b/lib/nusoap/docs/docs/nusoap/soapval.html deleted file mode 100644 index 54e6c6988..000000000 --- a/lib/nusoap/docs/docs/nusoap/soapval.html +++ /dev/null @@ -1,523 +0,0 @@ - - - - - - Docs For Class soapval - - - - -
    -

     Class soapval

    - - -
    -
    Description
    - -
    - -

    For creating serializable abstractions of native PHP types. This class

    -

    allows element name/namespace, XSD type, and XML attributes to be associated with a value. This is extremely useful when WSDL is not used, but is also useful when WSDL is used with polymorphic types, including xsd:anyType and user-defined types.

    -
      -
    • access: public
    • -
    • version: $Id: soapval.html,v 1.2 2010/04/26 20:25:21 snichol Exp $
    • -
    • author: Dietrich Ayala <dietrich@ganx4.com>
    • -
    -

    - Located in /nusoap.php (line 2066) -

    - - -
    nusoap_base
    -   |
    -   --soapval
    - -
    -
    - - - - -
    -
    Variable Summary
    - -
    -
    -
    -  - mixed - $attributes -
    -
    -  - mixed - $element_ns -
    -
    -  - string - $name -
    -
    -  - mixed - $type -
    -
    -  - mixed - $type_ns -
    -
    -  - mixed - $value -
    -
    -
    -
    - - -
    -
    Method Summary
    - -
    -
    - -
    -  - soapval - soapval - ([string $name = 'soapval'], [mixed $type = false], [mixed $value = -1], [mixed $element_ns = false], [mixed $type_ns = false], [mixed $attributes = false]) -
    - -
    -  - mixed - decode - () -
    - -
    -  - string - serialize - ([string $use = 'encoded']) -
    -
    -
    -
    - - -
    -
    Variables
    - -
    - -
    - -
    - - - mixed - $attributes - (line 2108) - -
    - - -

    The XML element attributes (array or false)

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - mixed - $element_ns - (line 2094) - -
    - - -

    The XML element namespace (string or false)

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - string - $name - (line 2073) - -
    - - -

    The XML element name

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - mixed - $type - (line 2080) - -
    - - -

    The XML type name (string or false)

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - mixed - $type_ns - (line 2101) - -
    - - -

    The XML type namespace (string or false)

    -
      -
    • access: private
    • -
    - - - - - -
    - -
    - -
    - - - mixed - $value - (line 2087) - -
    - - -

    The PHP value

    -
      -
    • access: private
    • -
    - - - - - -
    -

    Inherited Variables

    - -

    Inherited from nusoap_base

    -
    - - - nusoap_base::$charencoding
    -
    - - - nusoap_base::$debugLevel
    -
    - - - nusoap_base::$debug_str
    -
    - - - nusoap_base::$error_str
    -
    - - - nusoap_base::$namespaces
    -
    - - - nusoap_base::$revision
    -
    - - - nusoap_base::$soap_defencoding
    -
    - - - nusoap_base::$title
    -
    - - - nusoap_base::$typemap
    -
    - - - nusoap_base::$usedNamespaces
    -
    - - - nusoap_base::$version
    -
    - - - nusoap_base::$xmlEntities
    -
    - - - nusoap_base::$XMLSchemaVersion
    -
    -
    - -
    -
    - - -
    -
    Methods
    - -
    - - -
    - -
    - - Constructor soapval (line 2121) -
    - - -

    constructor

    -
      -
    • access: public
    • -
    - -
    - soapval - - soapval - - ([string $name = 'soapval'], [mixed $type = false], [mixed $value = -1], [mixed $element_ns = false], [mixed $type_ns = false], [mixed $attributes = false]) -
    - -
      -
    • - string - $name: optional name
    • -
    • - mixed - $type: optional type name
    • -
    • - mixed - $value: optional value
    • -
    • - mixed - $element_ns: optional namespace of value
    • -
    • - mixed - $type_ns: optional namespace of type
    • -
    • - mixed - $attributes: associative array of attributes to add to element serialization
    • -
    - - -
    - -
    - -
    - - decode (line 2148) -
    - - -

    decodes a soapval object into a PHP native type

    -
      -
    • access: public
    • -
    - -
    - mixed - - decode - - () -
    - - - -
    - -
    - -
    - - serialize (line 2138) -
    - - -

    return serialized value

    -
      -
    • return: XML data
    • -
    • access: public
    • -
    - -
    - string - - serialize - - ([string $use = 'encoded']) -
    - -
      -
    • - string - $use: The WSDL use value (encoded|literal)
    • -
    - - -
    -

    Inherited Methods

    - - -

    Inherited From nusoap_base

    -
    -  - nusoap_base::nusoap_base()
    -  - nusoap_base::appendDebug()
    -  - nusoap_base::clearDebug()
    -  - nusoap_base::contractQname()
    -  - nusoap_base::debug()
    -  - nusoap_base::expandEntities()
    -  - nusoap_base::expandQname()
    -  - nusoap_base::formatDump()
    -  - nusoap_base::getDebug()
    -  - nusoap_base::getDebugAsXMLComment()
    -  - nusoap_base::getDebugLevel()
    -  - nusoap_base::getError()
    -  - nusoap_base::getGlobalDebugLevel()
    -  - nusoap_base::getLocalPart()
    -  - nusoap_base::getmicrotime()
    -  - nusoap_base::getNamespaceFromPrefix()
    -  - nusoap_base::getPrefix()
    -  - nusoap_base::getPrefixFromNamespace()
    -  - nusoap_base::isArraySimpleOrStruct()
    -  - nusoap_base::serializeEnvelope()
    -  - nusoap_base::serialize_val()
    -  - nusoap_base::setDebugLevel()
    -  - nusoap_base::setError()
    -  - nusoap_base::setGlobalDebugLevel()
    -  - nusoap_base::varDump()
    -  - nusoap_base::__toString()
    -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:05 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/wsdl.html b/lib/nusoap/docs/docs/nusoap/wsdl.html deleted file mode 100644 index b92ff1faa..000000000 --- a/lib/nusoap/docs/docs/nusoap/wsdl.html +++ /dev/null @@ -1,2129 +0,0 @@ - - - - - - Docs For Class wsdl - - - - -
    -

     Class wsdl

    - - -
    -
    Description
    - -
    - -

    parses a WSDL file, allows access to it's data, other utility methods.

    -

    also builds WSDL structures programmatically.

    - -

    - Located in /nusoap.php (line 4596) -

    - - -
    nusoap_base
    -   |
    -   --wsdl
    - -
    -
    - - - - -
    -
    Variable Summary
    - -
    -
    -
    -  - mixed - $authtype -
    -
    -  - mixed - $bindings -
    -
    -  - mixed - $certRequest -
    -
    -  - mixed - $complexTypes -
    -
    -  - mixed - $curl_options -
    -
    -  - mixed - $currentBinding -
    -
    -  - mixed - $currentMessage -
    -
    -  - mixed - $currentOperation -
    -
    -  - mixed - $currentPort -
    -
    -  - mixed - $currentPortType -
    -
    -  - mixed - $currentSchema -
    -
    -  - mixed - $depth -
    -
    -  - mixed - $depth_array -
    -
    -  - mixed - $documentation -
    -
    -  - mixed - $endpoint -
    -
    -  - mixed - $import -
    -
    -  - mixed - $message -
    -
    -  - mixed - $messages -
    -
    -  - mixed - $opData -
    -
    -  - mixed - $parser -
    -
    -  - mixed - $password -
    -
    -  - mixed - $ports -
    -
    -  - mixed - $portTypes -
    -
    -  - mixed - $position -
    -
    -  - mixed - $proxyhost -
    -
    -  - mixed - $proxypassword -
    -
    -  - mixed - $proxyport -
    -
    -  - mixed - $proxyusername -
    -
    -  - mixed - $response_timeout -
    -
    -  - mixed - $schemas -
    -
    -  - mixed - $status -
    -
    -  - mixed - $timeout -
    -
    -  - mixed - $username -
    -
    -  - mixed - $use_curl -
    -
    -  - mixed - $wsdl -
    -
    -
    -
    - - -
    -
    Method Summary
    - -
    -
    - -
    -  - wsdl - wsdl - ([string $wsdl = ''], [string $proxyhost = false], [string $proxyport = false], [string $proxyusername = false], [string $proxypassword = false], integer $timeout, [integer $response_timeout = 30], [array $curl_options = null], [boolean $use_curl = false]) -
    - -
    -  - void - addComplexType - (string $name, [string $typeClass = 'complexType'], [string $phpType = 'array'], [string $compositor = ''], [string $restrictionBase = ''], [array $elements = array()], [array $attrs = array()], [string $arrayType = '']) -
    - -
    -  - void - addElement - (array $attrs) -
    - -
    -  - void - addOperation - (string $name, [array $in = false], [array $out = false], [string $namespace = false], [string $soapaction = false], [string $style = 'rpc'], [string $use = 'encoded'], [string $documentation = ''], [string $encodingStyle = '']) -
    - -
    -  - void - addSimpleType - (string $name, [string $restrictionBase = ''], [string $typeClass = 'simpleType'], [string $phpType = 'scalar'], [array $enumeration = array()]) -
    - -
    -  - void - character_data - (string $parser, string $data) -
    - -
    -  - void - end_element - (string $parser, string $name) -
    - -
    -  - void - fetchWSDL - (mixed $wsdl) -
    - -
    -  - void - getBindingData - (mixed $binding) -
    - -
    -  - array - getOperationData - (string $operation, [string $bindingType = 'soap']) -
    - -
    -  - array - getOperationDataForSoapAction - (string $soapAction, [string $bindingType = 'soap']) -
    - -
    -  - array - getOperations - ([string $portName = ''], [string $bindingType = 'soap']) -
    - -
    -  - mixed - getTypeDef - (string $type, string $ns) -
    - -
    -  - boolean - parametersMatchWrapped - (string $type, array &$parameters) -
    - -
    -  - void - parseWSDL - ([string $wsdl = '']) -
    - -
    -  - string - serialize - (mixed $debug) -
    - -
    -  - string - serializeComplexTypeAttributes - (array $typeDef, mixed $value, string $ns, string $uqType) -
    - -
    -  - string - serializeComplexTypeElements - (array $typeDef, mixed $value, string $ns, string $uqType, [string $use = 'encoded'], [string $encodingStyle = false]) -
    - -
    -  - mixed - serializeParameters - (string $operation, string $direction, mixed $parameters) -
    - -
    -  - mixed - serializeRPCParameters - (string $operation, string $direction, mixed $parameters, [string $bindingType = 'soap']) -
    - -
    -  - string - serializeType - (string $name, string $type, mixed $value, [string $use = 'encoded'], [string $encodingStyle = false], [boolean $unqualified = false]) -
    - -
    -  - void - setCredentials - (string $username, string $password, [string $authtype = 'basic'], [array $certRequest = array()]) -
    - -
    -  - void - start_element - (string $parser, string $name, string $attrs) -
    - -
    -  - void - webDescription - () -
    -
    -
    -
    - - -
    -
    Variables
    - -
    - -
    - -
    - - - mixed - $authtype - = '' (line 4636) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $bindings - = array() (line 4609) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $certRequest - = array() (line 4637) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $complexTypes - = array() (line 4603) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $curl_options - = array() (line 4631) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $currentBinding - (line 4610) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $currentMessage - (line 4605) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $currentOperation - (line 4606) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $currentPort - (line 4612) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $currentPortType - (line 4608) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $currentSchema - (line 4601) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $depth - = 0 (line 4622) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $depth_array - = array() (line 4623) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $documentation - = false (line 4615) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $endpoint - = '' (line 4616) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $import - = array() (line 4618) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $message - = array() (line 4602) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $messages - = array() (line 4604) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $opData - = array() (line 4613) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $parser - (line 4620) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $password - = '' (line 4635) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $ports - = array() (line 4611) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $portTypes - = array() (line 4607) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $position - = 0 (line 4621) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $proxyhost - = '' (line 4625) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $proxypassword - = '' (line 4628) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $proxyport - = '' (line 4626) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $proxyusername - = '' (line 4627) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $response_timeout - = 30 (line 4630) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $schemas - = array() (line 4600) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $status - = '' (line 4614) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $timeout - = 0 (line 4629) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $username - = '' (line 4634) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $use_curl - = false (line 4632) - -
    - - - - - - - -
    - -
    - -
    - - - mixed - $wsdl - (line 4598) - -
    - - - - - - - -
    -

    Inherited Variables

    - -

    Inherited from nusoap_base

    -
    - - - nusoap_base::$charencoding
    -
    - - - nusoap_base::$debugLevel
    -
    - - - nusoap_base::$debug_str
    -
    - - - nusoap_base::$error_str
    -
    - - - nusoap_base::$namespaces
    -
    - - - nusoap_base::$revision
    -
    - - - nusoap_base::$soap_defencoding
    -
    - - - nusoap_base::$title
    -
    - - - nusoap_base::$typemap
    -
    - - - nusoap_base::$usedNamespaces
    -
    - - - nusoap_base::$version
    -
    - - - nusoap_base::$xmlEntities
    -
    - - - nusoap_base::$XMLSchemaVersion
    -
    -
    - -
    -
    - - -
    -
    Methods
    - -
    - - -
    - -
    - - Constructor wsdl (line 4653) -
    - - -

    constructor

    -
      -
    • access: public
    • -
    - -
    - wsdl - - wsdl - - ([string $wsdl = ''], [string $proxyhost = false], [string $proxyport = false], [string $proxyusername = false], [string $proxypassword = false], integer $timeout, [integer $response_timeout = 30], [array $curl_options = null], [boolean $use_curl = false]) -
    - -
      -
    • - string - $wsdl: WSDL document URL
    • -
    • - string - $proxyhost
    • -
    • - string - $proxyport
    • -
    • - string - $proxyusername
    • -
    • - string - $proxypassword
    • -
    • - integer - $timeout: set the connection timeout
    • -
    • - integer - $response_timeout: set the response timeout
    • -
    • - array - $curl_options: user-specified cURL options
    • -
    • - boolean - $use_curl: try to use cURL
    • -
    - - -
    - -
    - -
    - - addComplexType (line 6278) -
    - - -

    adds an XML Schema complex type to the WSDL types

    - - -
    - void - - addComplexType - - (string $name, [string $typeClass = 'complexType'], [string $phpType = 'array'], [string $compositor = ''], [string $restrictionBase = ''], [array $elements = array()], [array $attrs = array()], [string $arrayType = '']) -
    - -
      -
    • - string - $name
    • -
    • - string - $typeClass: (complexType|simpleType|attribute)
    • -
    • - string - $phpType: currently supported are array and struct (php assoc array)
    • -
    • - string - $compositor: (all|sequence|choice)
    • -
    • - string - $restrictionBase: namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
    • -
    • - array - $elements: e.g. array ( name => array(name=>'',type=>'') )
    • -
    • - array - $attrs: e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
    • -
    • - string - $arrayType: as namespace:name (xsd:string)
    • -
    - - -
    - -
    - -
    - - addElement (line 6339) -
    - - -

    adds an element to the WSDL types

    - - -
    - void - - addElement - - (array $attrs) -
    - -
      -
    • - array - $attrs: attributes that must include name and type
    • -
    - - -
    - -
    - -
    - - addOperation (line 6358) -
    - - -

    register an operation with the server

    -
      -
    • access: public
    • -
    - -
    - void - - addOperation - - (string $name, [array $in = false], [array $out = false], [string $namespace = false], [string $soapaction = false], [string $style = 'rpc'], [string $use = 'encoded'], [string $documentation = ''], [string $encodingStyle = '']) -
    - -
      -
    • - string - $name: operation (method) name
    • -
    • - array - $in: assoc array of input values: key = param name, value = param type
    • -
    • - array - $out: assoc array of output values: key = param name, value = param type
    • -
    • - string - $namespace: optional The namespace for the operation
    • -
    • - string - $soapaction: optional The soapaction for the operation
    • -
    • - string - $style: (rpc|document) optional The style for the operation Note: when 'document' is specified, parameter and return wrappers are created for you automatically
    • -
    • - string - $use: (encoded|literal) optional The use for the parameters (cannot mix right now)
    • -
    • - string - $documentation: optional The description to include in the WSDL
    • -
    • - string - $encodingStyle: optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
    • -
    - - -
    - -
    - -
    - - addSimpleType (line 6325) -
    - - -

    adds an XML Schema simple type to the WSDL types

    - - -
    - void - - addSimpleType - - (string $name, [string $restrictionBase = ''], [string $typeClass = 'simpleType'], [string $phpType = 'scalar'], [array $enumeration = array()]) -
    - -
      -
    • - string - $name
    • -
    • - string - $restrictionBase: namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
    • -
    • - string - $typeClass: (should always be simpleType)
    • -
    • - string - $phpType: (should always be scalar)
    • -
    • - array - $enumeration: array of values
    • -
    - - -
    - -
    - -
    - - character_data (line 5123) -
    - - -

    element content handler

    -
      -
    • access: private
    • -
    - -
    - void - - character_data - - (string $parser, string $data) -
    - -
      -
    • - string - $parser: XML parser object
    • -
    • - string - $data: element content
    • -
    - - -
    - -
    - -
    - - end_element (line 5093) -
    - - -

    end-element handler

    -
      -
    • access: private
    • -
    - -
    - void - - end_element - - (string $parser, string $name) -
    - -
      -
    • - string - $parser: XML parser object
    • -
    • - string - $name: element name
    • -
    - - -
    - -
    - -
    - - fetchWSDL (line 4673) -
    - - -

    fetches the WSDL document and parses it

    -
      -
    • access: public
    • -
    - -
    - void - - fetchWSDL - - (mixed $wsdl) -
    - - - -
    - -
    - -
    - - getBindingData (line 5152) -
    - - - -
    - void - - getBindingData - - (mixed $binding) -
    - - - -
    - -
    - -
    - - getOperationData (line 5207) -
    - - -

    returns an associative array of data necessary for calling an operation

    -
      -
    • access: public
    • -
    - -
    - array - - getOperationData - - (string $operation, [string $bindingType = 'soap']) -
    - -
      -
    • - string - $operation: name of operation
    • -
    • - string - $bindingType: type of binding eg: soap, soap12
    • -
    - - -
    - -
    - -
    - - getOperationDataForSoapAction (line 5239) -
    - - -

    returns an associative array of data necessary for calling an operation

    -
      -
    • access: public
    • -
    - -
    - array - - getOperationDataForSoapAction - - (string $soapAction, [string $bindingType = 'soap']) -
    - -
      -
    • - string - $soapAction: soapAction for operation
    • -
    • - string - $bindingType: type of binding eg: soap, soap12
    • -
    - - -
    - -
    - -
    - - getOperations (line 5167) -
    - - -

    returns an assoc array of operation names => operation data

    -
      -
    • access: public
    • -
    - -
    - array - - getOperations - - ([string $portName = ''], [string $bindingType = 'soap']) -
    - -
      -
    • - string - $portName: WSDL port name
    • -
    • - string - $bindingType: eg: soap, smtp, dime (only soap and soap12 are currently supported)
    • -
    - - -
    - -
    - -
    - - getTypeDef (line 5277) -
    - - -

    returns an array of information about a given type returns false if no type exists by the given name

    -

    typeDef = array( 'elements' => array(), // refs to elements array 'restrictionBase' => '', 'phpType' => '', 'order' => '(sequence|all)', 'attrs' => array() // refs to attributes array )

    - - -
    - mixed - - getTypeDef - - (string $type, string $ns) -
    - -
      -
    • - string - $type: the type
    • -
    • - string - $ns: namespace (not prefix) of the type
    • -
    - - -
    - -
    - -
    - - parametersMatchWrapped (line 5525) -
    - - -

    determine whether a set of parameters are unwrapped when they are expect to be wrapped, Microsoft-style.

    -
      -
    • return: whether they parameters are unwrapped (and should be wrapped)
    • -
    • access: private
    • -
    - -
    - boolean - - parametersMatchWrapped - - (string $type, array &$parameters) -
    - -
      -
    • - string - $type: the type (element name) of the wrapper
    • -
    • - array - $parameters: the parameter values for the SOAP call
    • -
    - - -
    - -
    - -
    - - parseWSDL (line 4776) -
    - - -

    parses the wsdl document

    -
      -
    • access: private
    • -
    - -
    - void - - parseWSDL - - ([string $wsdl = '']) -
    - -
      -
    • - string - $wsdl: path or URL
    • -
    - - -
    - -
    - -
    - - serialize (line 5386) -
    - - -

    serialize the parsed wsdl

    -
      -
    • return: serialization of WSDL
    • -
    • access: public
    • -
    - -
    - string - - serialize - - (mixed $debug) -
    - -
      -
    • - mixed - $debug: whether to put debug=1 in endpoint URL
    • -
    - - -
    - -
    - -
    - - serializeComplexTypeAttributes (line 6107) -
    - - -

    serializes the attributes for a complexType

    -
      -
    • return: value serialized as an XML string
    • -
    • access: private
    • -
    - -
    - string - - serializeComplexTypeAttributes - - (array $typeDef, mixed $value, string $ns, string $uqType) -
    - -
      -
    • - array - $typeDef: our internal representation of an XML schema type (or element)
    • -
    • - mixed - $value: a native PHP value (parameter value)
    • -
    • - string - $ns: the namespace of the type
    • -
    • - string - $uqType: the local part of the type
    • -
    - - -
    - -
    - -
    - - serializeComplexTypeElements (line 6170) -
    - - -

    serializes the elements for a complexType

    -
      -
    • return: value serialized as an XML string
    • -
    • access: private
    • -
    - -
    - string - - serializeComplexTypeElements - - (array $typeDef, mixed $value, string $ns, string $uqType, [string $use = 'encoded'], [string $encodingStyle = false]) -
    - -
      -
    • - array - $typeDef: our internal representation of an XML schema type (or element)
    • -
    • - mixed - $value: a native PHP value (parameter value)
    • -
    • - string - $ns: the namespace of the type
    • -
    • - string - $uqType: the local part of the type
    • -
    • - string - $use: use for part (encoded|literal)
    • -
    • - string - $encodingStyle: SOAP encoding style for the value (if different than the enclosing style)
    • -
    - - -
    - -
    - -
    - - serializeParameters (line 5709) -
    - - -

    serialize a PHP value according to a WSDL message definition

    -

    TODO

    • multi-ref serialization
    • validate PHP values against type definitions, return errors if invalid

    -
      -
    • return: parameters serialized as XML or false on error (e.g. operation not found)
    • -
    • deprecated:
    • -
    • access: public
    • -
    - -
    - mixed - - serializeParameters - - (string $operation, string $direction, mixed $parameters) -
    - -
      -
    • - string - $operation: operation name
    • -
    • - string - $direction: (input|output)
    • -
    • - mixed - $parameters: parameter value(s)
    • -
    - - -
    - -
    - -
    - - serializeRPCParameters (line 5608) -
    - - -

    serialize PHP values according to a WSDL message definition contrary to the method name, this is not limited to RPC

    -

    TODO

    • multi-ref serialization
    • validate PHP values against type definitions, return errors if invalid

    -
      -
    • return: parameters serialized as XML or false on error (e.g. operation not found)
    • -
    • access: public
    • -
    - -
    - mixed - - serializeRPCParameters - - (string $operation, string $direction, mixed $parameters, [string $bindingType = 'soap']) -
    - -
      -
    • - string - $operation: operation name
    • -
    • - string - $direction: (input|output)
    • -
    • - mixed - $parameters: parameter value(s)
    • -
    • - string - $bindingType: (soap|soap12)
    • -
    - - -
    - -
    - -
    - - serializeType (line 5788) -
    - - -

    serializes a PHP value according a given type definition

    -
      -
    • return: value serialized as an XML string
    • -
    • access: private
    • -
    - -
    - string - - serializeType - - (string $name, string $type, mixed $value, [string $use = 'encoded'], [string $encodingStyle = false], [boolean $unqualified = false]) -
    - -
      -
    • - string - $name: name of value (part or element)
    • -
    • - string - $type: XML schema type of value (type or element)
    • -
    • - mixed - $value: a native PHP value (parameter value)
    • -
    • - string - $use: use for part (encoded|literal)
    • -
    • - string - $encodingStyle: SOAP encoding style for the value (if different than the enclosing style)
    • -
    • - boolean - $unqualified: a kludge for what should be XML namespace form handling
    • -
    - - -
    - -
    - -
    - - setCredentials (line 5143) -
    - - -

    if authenticating, set user credentials here

    -
      -
    • access: public
    • -
    - -
    - void - - setCredentials - - (string $username, string $password, [string $authtype = 'basic'], [array $certRequest = array()]) -
    - -
      -
    • - string - $username
    • -
    • - string - $password
    • -
    • - string - $authtype: (basic|digest|certificate|ntlm)
    • -
    • - array - $certRequest: (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
    • -
    - - -
    - -
    - -
    - - start_element (line 4880) -
    - - -

    start-element handler

    -
      -
    • access: private
    • -
    - -
    - void - - start_element - - (string $parser, string $name, string $attrs) -
    - -
      -
    • - string - $parser: XML parser object
    • -
    • - string - $name: element name
    • -
    • - string - $attrs: associative array of attributes
    • -
    - - -
    - -
    - -
    - - webDescription (line 5337) -
    - - -

    prints html description of services

    -
      -
    • access: private
    • -
    - -
    - void - - webDescription - - () -
    - - - -
    -

    Inherited Methods

    - - -

    Inherited From nusoap_base

    -
    -  - nusoap_base::nusoap_base()
    -  - nusoap_base::appendDebug()
    -  - nusoap_base::clearDebug()
    -  - nusoap_base::contractQname()
    -  - nusoap_base::debug()
    -  - nusoap_base::expandEntities()
    -  - nusoap_base::expandQname()
    -  - nusoap_base::formatDump()
    -  - nusoap_base::getDebug()
    -  - nusoap_base::getDebugAsXMLComment()
    -  - nusoap_base::getDebugLevel()
    -  - nusoap_base::getError()
    -  - nusoap_base::getGlobalDebugLevel()
    -  - nusoap_base::getLocalPart()
    -  - nusoap_base::getmicrotime()
    -  - nusoap_base::getNamespaceFromPrefix()
    -  - nusoap_base::getPrefix()
    -  - nusoap_base::getPrefixFromNamespace()
    -  - nusoap_base::isArraySimpleOrStruct()
    -  - nusoap_base::serializeEnvelope()
    -  - nusoap_base::serialize_val()
    -  - nusoap_base::setDebugLevel()
    -  - nusoap_base::setError()
    -  - nusoap_base::setGlobalDebugLevel()
    -  - nusoap_base::varDump()
    -  - nusoap_base::__toString()
    -
    - -
    -
    - - -

    - Documentation generated on Mon, 26 Apr 2010 16:17:07 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/nusoap/wsdlcache.html b/lib/nusoap/docs/docs/nusoap/wsdlcache.html deleted file mode 100644 index 924eb8ba8..000000000 --- a/lib/nusoap/docs/docs/nusoap/wsdlcache.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - Docs For Class wsdlcache - - - - -
    -

     Class wsdlcache

    - - -
    -
    Description
    - -
    - -

    For backward compatibility

    - -

    - Located in /class.wsdlcache.php (line 207) -

    - - -
    nusoap_wsdlcache
    -   |
    -   --wsdlcache
    - -
    -
    - - - - - - -
    -
    Variables
    - -
    -

    Inherited Variables

    - -

    Inherited from nusoap_wsdlcache

    -
    - - - nusoap_wsdlcache::$cache_dir
    -
    - - - nusoap_wsdlcache::$cache_lifetime
    -
    - - - nusoap_wsdlcache::$debug_str
    -
    - - - nusoap_wsdlcache::$fplock
    -
    -
    - -
    -
    - - - - - -

    - Documentation generated on Mon, 26 Apr 2010 16:16:49 -0400 by phpDocumentor 1.3.0RC3 -

    -
    - \ No newline at end of file diff --git a/lib/nusoap/docs/docs/packages.html b/lib/nusoap/docs/docs/packages.html deleted file mode 100644 index 65732bec9..000000000 --- a/lib/nusoap/docs/docs/packages.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/nusoap/nusoap.php b/lib/nusoap/nusoap.php deleted file mode 100644 index 90a7a3b0a..000000000 --- a/lib/nusoap/nusoap.php +++ /dev/null @@ -1,8148 +0,0 @@ - -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_base { - /** - * Identification for HTTP headers. - * - * @var string - * @access private - */ - var $title = 'NuSOAP'; - /** - * Version for HTTP headers. - * - * @var string - * @access private - */ - var $version = '0.9.5'; - /** - * CVS revision for HTTP headers. - * - * @var string - * @access private - */ - var $revision = '$Revision: 1.123 $'; - /** - * Current error string (manipulated by getError/setError) - * - * @var string - * @access private - */ - var $error_str = ''; - /** - * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment) - * - * @var string - * @access private - */ - var $debug_str = ''; - /** - * toggles automatic encoding of special characters as entities - * (should always be true, I think) - * - * @var boolean - * @access private - */ - var $charencoding = true; - /** - * the debug level for this instance - * - * @var integer - * @access private - */ - var $debugLevel; - - /** - * set schema version - * - * @var string - * @access public - */ - var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema'; - - /** - * charset encoding for outgoing messages - * - * @var string - * @access public - */ - var $soap_defencoding = 'ISO-8859-1'; - //var $soap_defencoding = 'UTF-8'; - - /** - * namespaces in an array of prefix => uri - * - * this is "seeded" by a set of constants, but it may be altered by code - * - * @var array - * @access public - */ - var $namespaces = array( - 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/', - 'xsd' => 'http://www.w3.org/2001/XMLSchema', - 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance', - 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/' - ); - - /** - * namespaces used in the current context, e.g. during serialization - * - * @var array - * @access private - */ - var $usedNamespaces = array(); - - /** - * XML Schema types in an array of uri => (array of xml type => php type) - * is this legacy yet? - * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings. - * @var array - * @access public - */ - var $typemap = array( - 'http://www.w3.org/2001/XMLSchema' => array( - 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double', - 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'', - 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string', - // abstract "any" types - 'anyType'=>'string','anySimpleType'=>'string', - // derived datatypes - 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'', - 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer', - 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer', - 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''), - 'http://www.w3.org/2000/10/XMLSchema' => array( - 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double', - 'float'=>'double','dateTime'=>'string', - 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'), - 'http://www.w3.org/1999/XMLSchema' => array( - 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double', - 'float'=>'double','dateTime'=>'string', - 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'), - 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'), - 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'), - 'http://xml.apache.org/xml-soap' => array('Map') - ); - - /** - * XML entities to convert - * - * @var array - * @access public - * @deprecated - * @see expandEntities - */ - var $xmlEntities = array('quot' => '"','amp' => '&', - 'lt' => '<','gt' => '>','apos' => "'"); - - /** - * constructor - * - * @access public - */ - function nusoap_base() { - $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel']; - } - - /** - * gets the global debug level, which applies to future instances - * - * @return integer Debug level 0-9, where 0 turns off - * @access public - */ - function getGlobalDebugLevel() { - return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel']; - } - - /** - * sets the global debug level, which applies to future instances - * - * @param int $level Debug level 0-9, where 0 turns off - * @access public - */ - function setGlobalDebugLevel($level) { - $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level; - } - - /** - * gets the debug level for this instance - * - * @return int Debug level 0-9, where 0 turns off - * @access public - */ - function getDebugLevel() { - return $this->debugLevel; - } - - /** - * sets the debug level for this instance - * - * @param int $level Debug level 0-9, where 0 turns off - * @access public - */ - function setDebugLevel($level) { - $this->debugLevel = $level; - } - - /** - * adds debug data to the instance debug string with formatting - * - * @param string $string debug data - * @access private - */ - function debug($string){ - if ($this->debugLevel > 0) { - $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n"); - } - } - - /** - * adds debug data to the instance debug string without formatting - * - * @param string $string debug data - * @access public - */ - function appendDebug($string){ - if ($this->debugLevel > 0) { - // it would be nice to use a memory stream here to use - // memory more efficiently - $this->debug_str .= $string; - } - } - - /** - * clears the current debug data for this instance - * - * @access public - */ - function clearDebug() { - // it would be nice to use a memory stream here to use - // memory more efficiently - $this->debug_str = ''; - } - - /** - * gets the current debug data for this instance - * - * @return debug data - * @access public - */ - function &getDebug() { - // it would be nice to use a memory stream here to use - // memory more efficiently - return $this->debug_str; - } - - /** - * gets the current debug data for this instance as an XML comment - * this may change the contents of the debug data - * - * @return debug data as an XML comment - * @access public - */ - function &getDebugAsXMLComment() { - // it would be nice to use a memory stream here to use - // memory more efficiently - while (strpos($this->debug_str, '--')) { - $this->debug_str = str_replace('--', '- -', $this->debug_str); - } - $ret = ""; - return $ret; - } - - /** - * expands entities, e.g. changes '<' to '<'. - * - * @param string $val The string in which to expand entities. - * @access private - */ - function expandEntities($val) { - if ($this->charencoding) { - $val = str_replace('&', '&', $val); - $val = str_replace("'", ''', $val); - $val = str_replace('"', '"', $val); - $val = str_replace('<', '<', $val); - $val = str_replace('>', '>', $val); - } - return $val; - } - - /** - * returns error string if present - * - * @return mixed error string or false - * @access public - */ - function getError(){ - if($this->error_str != ''){ - return $this->error_str; - } - return false; - } - - /** - * sets error string - * - * @return boolean $string error string - * @access private - */ - function setError($str){ - $this->error_str = $str; - } - - /** - * detect if array is a simple array or a struct (associative array) - * - * @param mixed $val The PHP array - * @return string (arraySimple|arrayStruct) - * @access private - */ - function isArraySimpleOrStruct($val) { - $keyList = array_keys($val); - foreach ($keyList as $keyListValue) { - if (!is_int($keyListValue)) { - return 'arrayStruct'; - } - } - return 'arraySimple'; - } - - /** - * serializes PHP values in accordance w/ section 5. Type information is - * not serialized if $use == 'literal'. - * - * @param mixed $val The value to serialize - * @param string $name The name (local part) of the XML element - * @param string $type The XML schema type (local part) for the element - * @param string $name_ns The namespace for the name of the XML element - * @param string $type_ns The namespace for the type of the element - * @param array $attributes The attributes to serialize as name=>value pairs - * @param string $use The WSDL "use" (encoded|literal) - * @param boolean $soapval Whether this is called from soapval. - * @return string The serialized element, possibly with child elements - * @access public - */ - function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) { - $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval"); - $this->appendDebug('value=' . $this->varDump($val)); - $this->appendDebug('attributes=' . $this->varDump($attributes)); - - if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) { - $this->debug("serialize_val: serialize soapval"); - $xml = $val->serialize($use); - $this->appendDebug($val->getDebug()); - $val->clearDebug(); - $this->debug("serialize_val of soapval returning $xml"); - return $xml; - } - // force valid name if necessary - if (is_numeric($name)) { - $name = '__numeric_' . $name; - } elseif (! $name) { - $name = 'noname'; - } - // if name has ns, add ns prefix to name - $xmlns = ''; - if($name_ns){ - $prefix = 'nu'.rand(1000,9999); - $name = $prefix.':'.$name; - $xmlns .= " xmlns:$prefix=\"$name_ns\""; - } - // if type is prefixed, create type prefix - if($type_ns != '' && $type_ns == $this->namespaces['xsd']){ - // need to fix this. shouldn't default to xsd if no ns specified - // w/o checking against typemap - $type_prefix = 'xsd'; - } elseif($type_ns){ - $type_prefix = 'ns'.rand(1000,9999); - $xmlns .= " xmlns:$type_prefix=\"$type_ns\""; - } - // serialize attributes if present - $atts = ''; - if($attributes){ - foreach($attributes as $k => $v){ - $atts .= " $k=\"".$this->expandEntities($v).'"'; - } - } - // serialize null value - if (is_null($val)) { - $this->debug("serialize_val: serialize null"); - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$name$xmlns$atts/>"; - $this->debug("serialize_val returning $xml"); - return $xml; - } else { - if (isset($type) && isset($type_prefix)) { - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ''; - } - $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>"; - $this->debug("serialize_val returning $xml"); - return $xml; - } - } - // serialize if an xsd built-in primitive type - if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){ - $this->debug("serialize_val: serialize xsd built-in primitive type"); - if (is_bool($val)) { - if ($type == 'boolean') { - $val = $val ? 'true' : 'false'; - } elseif (! $val) { - $val = 0; - } - } else if (is_string($val)) { - $val = $this->expandEntities($val); - } - if ($use == 'literal') { - $xml = "<$name$xmlns$atts>$val"; - $this->debug("serialize_val returning $xml"); - return $xml; - } else { - $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val"; - $this->debug("serialize_val returning $xml"); - return $xml; - } - } - // detect type and serialize - $xml = ''; - switch(true) { - case (is_bool($val) || $type == 'boolean'): - $this->debug("serialize_val: serialize boolean"); - if ($type == 'boolean') { - $val = $val ? 'true' : 'false'; - } elseif (! $val) { - $val = 0; - } - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val"; - } - break; - case (is_int($val) || is_long($val) || $type == 'int'): - $this->debug("serialize_val: serialize int"); - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val"; - } - break; - case (is_float($val)|| is_double($val) || $type == 'float'): - $this->debug("serialize_val: serialize float"); - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val"; - } - break; - case (is_string($val) || $type == 'string'): - $this->debug("serialize_val: serialize string"); - $val = $this->expandEntities($val); - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$val"; - } else { - $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val"; - } - break; - case is_object($val): - $this->debug("serialize_val: serialize object"); - if (get_class($val) == 'soapval') { - $this->debug("serialize_val: serialize soapval object"); - $pXml = $val->serialize($use); - $this->appendDebug($val->getDebug()); - $val->clearDebug(); - } else { - if (! $name) { - $name = get_class($val); - $this->debug("In serialize_val, used class name $name as element name"); - } else { - $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val)); - } - foreach(get_object_vars($val) as $k => $v){ - $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use); - } - } - if(isset($type) && isset($type_prefix)){ - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ''; - } - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>$pXml"; - } else { - $xml .= "<$name$xmlns$type_str$atts>$pXml"; - } - break; - break; - case (is_array($val) || $type): - // detect if struct or array - $valueType = $this->isArraySimpleOrStruct($val); - if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){ - $this->debug("serialize_val: serialize array"); - $i = 0; - if(is_array($val) && count($val)> 0){ - foreach($val as $v){ - if(is_object($v) && get_class($v) == 'soapval'){ - $tt_ns = $v->type_ns; - $tt = $v->type; - } elseif (is_array($v)) { - $tt = $this->isArraySimpleOrStruct($v); - } else { - $tt = gettype($v); - } - $array_types[$tt] = 1; - // TODO: for literal, the name should be $name - $xml .= $this->serialize_val($v,'item',false,false,false,false,$use); - ++$i; - } - if(count($array_types) > 1){ - $array_typename = 'xsd:anyType'; - } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) { - if ($tt == 'integer') { - $tt = 'int'; - } - $array_typename = 'xsd:'.$tt; - } elseif(isset($tt) && $tt == 'arraySimple'){ - $array_typename = 'SOAP-ENC:Array'; - } elseif(isset($tt) && $tt == 'arrayStruct'){ - $array_typename = 'unnamed_struct_use_soapval'; - } else { - // if type is prefixed, create type prefix - if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){ - $array_typename = 'xsd:' . $tt; - } elseif ($tt_ns) { - $tt_prefix = 'ns' . rand(1000, 9999); - $array_typename = "$tt_prefix:$tt"; - $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\""; - } else { - $array_typename = $tt; - } - } - $array_type = $i; - if ($use == 'literal') { - $type_str = ''; - } else if (isset($type) && isset($type_prefix)) { - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\""; - } - // empty array - } else { - if ($use == 'literal') { - $type_str = ''; - } else if (isset($type) && isset($type_prefix)) { - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\""; - } - } - // TODO: for array in literal, there is no wrapper here - $xml = "<$name$xmlns$type_str$atts>".$xml.""; - } else { - // got a struct - $this->debug("serialize_val: serialize struct"); - if(isset($type) && isset($type_prefix)){ - $type_str = " xsi:type=\"$type_prefix:$type\""; - } else { - $type_str = ''; - } - if ($use == 'literal') { - $xml .= "<$name$xmlns$atts>"; - } else { - $xml .= "<$name$xmlns$type_str$atts>"; - } - foreach($val as $k => $v){ - // Apache Map - if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') { - $xml .= ''; - $xml .= $this->serialize_val($k,'key',false,false,false,false,$use); - $xml .= $this->serialize_val($v,'value',false,false,false,false,$use); - $xml .= ''; - } else { - $xml .= $this->serialize_val($v,$k,false,false,false,false,$use); - } - } - $xml .= ""; - } - break; - default: - $this->debug("serialize_val: serialize unknown"); - $xml .= 'not detected, got '.gettype($val).' for '.$val; - break; - } - $this->debug("serialize_val returning $xml"); - return $xml; - } - - /** - * serializes a message - * - * @param string $body the XML of the SOAP body - * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array - * @param array $namespaces optional the namespaces used in generating the body and headers - * @param string $style optional (rpc|document) - * @param string $use optional (encoded|literal) - * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) - * @return string the message - * @access public - */ - function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){ - // TODO: add an option to automatically run utf8_encode on $body and $headers - // if $this->soap_defencoding is UTF-8. Not doing this automatically allows - // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1 - - $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle"); - $this->debug("headers:"); - $this->appendDebug($this->varDump($headers)); - $this->debug("namespaces:"); - $this->appendDebug($this->varDump($namespaces)); - - // serialize namespaces - $ns_string = ''; - foreach(array_merge($this->namespaces,$namespaces) as $k => $v){ - $ns_string .= " xmlns:$k=\"$v\""; - } - if($encodingStyle) { - $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string"; - } - - // serialize headers - if($headers){ - if (is_array($headers)) { - $xml = ''; - foreach ($headers as $k => $v) { - if (is_object($v) && get_class($v) == 'soapval') { - $xml .= $this->serialize_val($v, false, false, false, false, false, $use); - } else { - $xml .= $this->serialize_val($v, $k, false, false, false, false, $use); - } - } - $headers = $xml; - $this->debug("In serializeEnvelope, serialized array of headers to $headers"); - } - $headers = "".$headers.""; - } - // serialize envelope - return - 'soap_defencoding .'"?'.">". - '". - $headers. - "". - $body. - "". - ""; - } - - /** - * formats a string to be inserted into an HTML stream - * - * @param string $str The string to format - * @return string The formatted string - * @access public - * @deprecated - */ - function formatDump($str){ - $str = htmlspecialchars($str); - return nl2br($str); - } - - /** - * contracts (changes namespace to prefix) a qualified name - * - * @param string $qname qname - * @return string contracted qname - * @access private - */ - function contractQname($qname){ - // get element namespace - //$this->xdebug("Contract $qname"); - if (strrpos($qname, ':')) { - // get unqualified name - $name = substr($qname, strrpos($qname, ':') + 1); - // get ns - $ns = substr($qname, 0, strrpos($qname, ':')); - $p = $this->getPrefixFromNamespace($ns); - if ($p) { - return $p . ':' . $name; - } - return $qname; - } else { - return $qname; - } - } - - /** - * expands (changes prefix to namespace) a qualified name - * - * @param string $qname qname - * @return string expanded qname - * @access private - */ - function expandQname($qname){ - // get element prefix - if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){ - // get unqualified name - $name = substr(strstr($qname,':'),1); - // get ns prefix - $prefix = substr($qname,0,strpos($qname,':')); - if(isset($this->namespaces[$prefix])){ - return $this->namespaces[$prefix].':'.$name; - } else { - return $qname; - } - } else { - return $qname; - } - } - - /** - * returns the local part of a prefixed string - * returns the original string, if not prefixed - * - * @param string $str The prefixed string - * @return string The local part - * @access public - */ - function getLocalPart($str){ - if($sstr = strrchr($str,':')){ - // get unqualified name - return substr( $sstr, 1 ); - } else { - return $str; - } - } - - /** - * returns the prefix part of a prefixed string - * returns false, if not prefixed - * - * @param string $str The prefixed string - * @return mixed The prefix or false if there is no prefix - * @access public - */ - function getPrefix($str){ - if($pos = strrpos($str,':')){ - // get prefix - return substr($str,0,$pos); - } - return false; - } - - /** - * pass it a prefix, it returns a namespace - * - * @param string $prefix The prefix - * @return mixed The namespace, false if no namespace has the specified prefix - * @access public - */ - function getNamespaceFromPrefix($prefix){ - if (isset($this->namespaces[$prefix])) { - return $this->namespaces[$prefix]; - } - //$this->setError("No namespace registered for prefix '$prefix'"); - return false; - } - - /** - * returns the prefix for a given namespace (or prefix) - * or false if no prefixes registered for the given namespace - * - * @param string $ns The namespace - * @return mixed The prefix, false if the namespace has no prefixes - * @access public - */ - function getPrefixFromNamespace($ns) { - foreach ($this->namespaces as $p => $n) { - if ($ns == $n || $ns == $p) { - $this->usedNamespaces[$p] = $n; - return $p; - } - } - return false; - } - - /** - * returns the time in ODBC canonical form with microseconds - * - * @return string The time in ODBC canonical form with microseconds - * @access public - */ - function getmicrotime() { - if (function_exists('gettimeofday')) { - $tod = gettimeofday(); - $sec = $tod['sec']; - $usec = $tod['usec']; - } else { - $sec = time(); - $usec = 0; - } - return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec); - } - - /** - * Returns a string with the output of var_dump - * - * @param mixed $data The variable to var_dump - * @return string The output of var_dump - * @access public - */ - function varDump($data) { - ob_start(); - var_dump($data); - $ret_val = ob_get_contents(); - ob_end_clean(); - return $ret_val; - } - - /** - * represents the object as a string - * - * @return string - * @access public - */ - function __toString() { - return $this->varDump($this); - } -} - -// XML Schema Datatype Helper Functions - -//xsd:dateTime helpers - -/** -* convert unix timestamp to ISO 8601 compliant date string -* -* @param int $timestamp Unix time stamp -* @param boolean $utc Whether the time stamp is UTC or local -* @return mixed ISO 8601 date string or false -* @access public -*/ -function timestamp_to_iso8601($timestamp,$utc=true){ - $datestr = date('Y-m-d\TH:i:sO',$timestamp); - $pos = strrpos($datestr, "+"); - if ($pos === FALSE) { - $pos = strrpos($datestr, "-"); - } - if ($pos !== FALSE) { - if (strlen($datestr) == $pos + 5) { - $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2); - } - } - if($utc){ - $pattern = '/'. - '([0-9]{4})-'. // centuries & years CCYY- - '([0-9]{2})-'. // months MM- - '([0-9]{2})'. // days DD - 'T'. // separator T - '([0-9]{2}):'. // hours hh: - '([0-9]{2}):'. // minutes mm: - '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss... - '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's - '/'; - - if(preg_match($pattern,$datestr,$regs)){ - return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]); - } - return false; - } else { - return $datestr; - } -} - -/** -* convert ISO 8601 compliant date string to unix timestamp -* -* @param string $datestr ISO 8601 compliant date string -* @return mixed Unix timestamp (int) or false -* @access public -*/ -function iso8601_to_timestamp($datestr){ - $pattern = '/'. - '([0-9]{4})-'. // centuries & years CCYY- - '([0-9]{2})-'. // months MM- - '([0-9]{2})'. // days DD - 'T'. // separator T - '([0-9]{2}):'. // hours hh: - '([0-9]{2}):'. // minutes mm: - '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss... - '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's - '/'; - if(preg_match($pattern,$datestr,$regs)){ - // not utc - if($regs[8] != 'Z'){ - $op = substr($regs[8],0,1); - $h = substr($regs[8],1,2); - $m = substr($regs[8],strlen($regs[8])-2,2); - if($op == '-'){ - $regs[4] = $regs[4] + $h; - $regs[5] = $regs[5] + $m; - } elseif($op == '+'){ - $regs[4] = $regs[4] - $h; - $regs[5] = $regs[5] - $m; - } - } - return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); -// return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z"); - } else { - return false; - } -} - -/** -* sleeps some number of microseconds -* -* @param string $usec the number of microseconds to sleep -* @access public -* @deprecated -*/ -function usleepWindows($usec) -{ - $start = gettimeofday(); - - do - { - $stop = gettimeofday(); - $timePassed = 1000000 * ($stop['sec'] - $start['sec']) - + $stop['usec'] - $start['usec']; - } - while ($timePassed < $usec); -} - -?> -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_fault extends nusoap_base { - /** - * The fault code (client|server) - * @var string - * @access private - */ - var $faultcode; - /** - * The fault actor - * @var string - * @access private - */ - var $faultactor; - /** - * The fault string, a description of the fault - * @var string - * @access private - */ - var $faultstring; - /** - * The fault detail, typically a string or array of string - * @var mixed - * @access private - */ - var $faultdetail; - - /** - * constructor - * - * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server) - * @param string $faultactor only used when msg routed between multiple actors - * @param string $faultstring human readable error message - * @param mixed $faultdetail detail, typically a string or array of string - */ - function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){ - parent::nusoap_base(); - $this->faultcode = $faultcode; - $this->faultactor = $faultactor; - $this->faultstring = $faultstring; - $this->faultdetail = $faultdetail; - } - - /** - * serialize a fault - * - * @return string The serialization of the fault instance. - * @access public - */ - function serialize(){ - $ns_string = ''; - foreach($this->namespaces as $k => $v){ - $ns_string .= "\n xmlns:$k=\"$v\""; - } - $return_msg = - 'soap_defencoding.'"?>'. - '\n". - ''. - ''. - $this->serialize_val($this->faultcode, 'faultcode'). - $this->serialize_val($this->faultactor, 'faultactor'). - $this->serialize_val($this->faultstring, 'faultstring'). - $this->serialize_val($this->faultdetail, 'detail'). - ''. - ''. - ''; - return $return_msg; - } -} - -/** - * Backward compatibility - */ -class soap_fault extends nusoap_fault { -} - -?> -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_xmlschema extends nusoap_base { - - // files - var $schema = ''; - var $xml = ''; - // namespaces - var $enclosingNamespaces; - // schema info - var $schemaInfo = array(); - var $schemaTargetNamespace = ''; - // types, elements, attributes defined by the schema - var $attributes = array(); - var $complexTypes = array(); - var $complexTypeStack = array(); - var $currentComplexType = null; - var $elements = array(); - var $elementStack = array(); - var $currentElement = null; - var $simpleTypes = array(); - var $simpleTypeStack = array(); - var $currentSimpleType = null; - // imports - var $imports = array(); - // parser vars - var $parser; - var $position = 0; - var $depth = 0; - var $depth_array = array(); - var $message = array(); - var $defaultNamespace = array(); - - /** - * constructor - * - * @param string $schema schema document URI - * @param string $xml xml document URI - * @param string $namespaces namespaces defined in enclosing XML - * @access public - */ - function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){ - parent::nusoap_base(); - $this->debug('nusoap_xmlschema class instantiated, inside constructor'); - // files - $this->schema = $schema; - $this->xml = $xml; - - // namespaces - $this->enclosingNamespaces = $namespaces; - $this->namespaces = array_merge($this->namespaces, $namespaces); - - // parse schema file - if($schema != ''){ - $this->debug('initial schema file: '.$schema); - $this->parseFile($schema, 'schema'); - } - - // parse xml file - if($xml != ''){ - $this->debug('initial xml file: '.$xml); - $this->parseFile($xml, 'xml'); - } - - } - - /** - * parse an XML file - * - * @param string $xml path/URL to XML file - * @param string $type (schema | xml) - * @return boolean - * @access public - */ - function parseFile($xml,$type){ - // parse xml file - if($xml != ""){ - $xmlStr = @join("",@file($xml)); - if($xmlStr == ""){ - $msg = 'Error reading XML from '.$xml; - $this->setError($msg); - $this->debug($msg); - return false; - } else { - $this->debug("parsing $xml"); - $this->parseString($xmlStr,$type); - $this->debug("done parsing $xml"); - return true; - } - } - return false; - } - - /** - * parse an XML string - * - * @param string $xml path or URL - * @param string $type (schema|xml) - * @access private - */ - function parseString($xml,$type){ - // parse xml string - if($xml != ""){ - - // Create an XML parser. - $this->parser = xml_parser_create(); - // Set the options for parsing the XML data. - xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); - - // Set the object for the parser. - xml_set_object($this->parser, $this); - - // Set the element handlers for the parser. - if($type == "schema"){ - xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement'); - xml_set_character_data_handler($this->parser,'schemaCharacterData'); - } elseif($type == "xml"){ - xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement'); - xml_set_character_data_handler($this->parser,'xmlCharacterData'); - } - - // Parse the XML file. - if(!xml_parse($this->parser,$xml,true)){ - // Display an error message. - $errstr = sprintf('XML error parsing XML schema on line %d: %s', - xml_get_current_line_number($this->parser), - xml_error_string(xml_get_error_code($this->parser)) - ); - $this->debug($errstr); - $this->debug("XML payload:\n" . $xml); - $this->setError($errstr); - } - - xml_parser_free($this->parser); - } else{ - $this->debug('no xml passed to parseString()!!'); - $this->setError('no xml passed to parseString()!!'); - } - } - - /** - * gets a type name for an unnamed type - * - * @param string Element name - * @return string A type name for an unnamed type - * @access private - */ - function CreateTypeName($ename) { - $scope = ''; - for ($i = 0; $i < count($this->complexTypeStack); $i++) { - $scope .= $this->complexTypeStack[$i] . '_'; - } - return $scope . $ename . '_ContainedType'; - } - - /** - * start-element handler - * - * @param string $parser XML parser object - * @param string $name element name - * @param string $attrs associative array of attributes - * @access private - */ - function schemaStartElement($parser, $name, $attrs) { - - // position in the total number of elements, starting from 0 - $pos = $this->position++; - $depth = $this->depth++; - // set self as current value for this depth - $this->depth_array[$depth] = $pos; - $this->message[$pos] = array('cdata' => ''); - if ($depth > 0) { - $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]]; - } else { - $this->defaultNamespace[$pos] = false; - } - - // get element prefix - if($prefix = $this->getPrefix($name)){ - // get unqualified name - $name = $this->getLocalPart($name); - } else { - $prefix = ''; - } - - // loop thru attributes, expanding, and registering namespace declarations - if(count($attrs) > 0){ - foreach($attrs as $k => $v){ - // if ns declarations, add to class level array of valid namespaces - if(preg_match('/^xmlns/',$k)){ - //$this->xdebug("$k: $v"); - //$this->xdebug('ns_prefix: '.$this->getPrefix($k)); - if($ns_prefix = substr(strrchr($k,':'),1)){ - //$this->xdebug("Add namespace[$ns_prefix] = $v"); - $this->namespaces[$ns_prefix] = $v; - } else { - $this->defaultNamespace[$pos] = $v; - if (! $this->getPrefixFromNamespace($v)) { - $this->namespaces['ns'.(count($this->namespaces)+1)] = $v; - } - } - if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){ - $this->XMLSchemaVersion = $v; - $this->namespaces['xsi'] = $v.'-instance'; - } - } - } - foreach($attrs as $k => $v){ - // expand each attribute - $k = strpos($k,':') ? $this->expandQname($k) : $k; - $v = strpos($v,':') ? $this->expandQname($v) : $v; - $eAttrs[$k] = $v; - } - $attrs = $eAttrs; - } else { - $attrs = array(); - } - // find status, register data - switch($name){ - case 'all': // (optional) compositor content for a complexType - case 'choice': - case 'group': - case 'sequence': - //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement"); - $this->complexTypes[$this->currentComplexType]['compositor'] = $name; - //if($name == 'all' || $name == 'sequence'){ - // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; - //} - break; - case 'attribute': // complexType attribute - //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']); - $this->xdebug("parsing attribute:"); - $this->appendDebug($this->varDump($attrs)); - if (!isset($attrs['form'])) { - // TODO: handle globals - $attrs['form'] = $this->schemaInfo['attributeFormDefault']; - } - if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) { - $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - if (!strpos($v, ':')) { - // no namespace in arrayType attribute value... - if ($this->defaultNamespace[$pos]) { - // ...so use the default - $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - } - } - } - if(isset($attrs['name'])){ - $this->attributes[$attrs['name']] = $attrs; - $aname = $attrs['name']; - } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){ - if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) { - $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - } else { - $aname = ''; - } - } elseif(isset($attrs['ref'])){ - $aname = $attrs['ref']; - $this->attributes[$attrs['ref']] = $attrs; - } - - if($this->currentComplexType){ // This should *always* be - $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs; - } - // arrayType attribute - if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){ - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - $prefix = $this->getPrefix($aname); - if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){ - $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']; - } else { - $v = ''; - } - if(strpos($v,'[,]')){ - $this->complexTypes[$this->currentComplexType]['multidimensional'] = true; - } - $v = substr($v,0,strpos($v,'[')); // clip the [] - if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){ - $v = $this->XMLSchemaVersion.':'.$v; - } - $this->complexTypes[$this->currentComplexType]['arrayType'] = $v; - } - break; - case 'complexContent': // (optional) content for a complexType - $this->xdebug("do nothing for element $name"); - break; - case 'complexType': - array_push($this->complexTypeStack, $this->currentComplexType); - if(isset($attrs['name'])){ - // TODO: what is the scope of named complexTypes that appear - // nested within other c complexTypes? - $this->xdebug('processing named complexType '.$attrs['name']); - //$this->currentElement = false; - $this->currentComplexType = $attrs['name']; - $this->complexTypes[$this->currentComplexType] = $attrs; - $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType'; - // This is for constructs like - // - // - // - // - // - if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){ - $this->xdebug('complexType is unusual array'); - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - } else { - $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; - } - } else { - $name = $this->CreateTypeName($this->currentElement); - $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name); - $this->currentComplexType = $name; - //$this->currentElement = false; - $this->complexTypes[$this->currentComplexType] = $attrs; - $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType'; - // This is for constructs like - // - // - // - // - // - if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){ - $this->xdebug('complexType is unusual array'); - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - } else { - $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; - } - } - $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false'; - break; - case 'element': - array_push($this->elementStack, $this->currentElement); - if (!isset($attrs['form'])) { - if ($this->currentComplexType) { - $attrs['form'] = $this->schemaInfo['elementFormDefault']; - } else { - // global - $attrs['form'] = 'qualified'; - } - } - if(isset($attrs['type'])){ - $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']); - if (! $this->getPrefix($attrs['type'])) { - if ($this->defaultNamespace[$pos]) { - $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type']; - $this->xdebug('used default namespace to make type ' . $attrs['type']); - } - } - // This is for constructs like - // - // - // - // - // - if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') { - $this->xdebug('arrayType for unusual array is ' . $attrs['type']); - $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type']; - } - $this->currentElement = $attrs['name']; - $ename = $attrs['name']; - } elseif(isset($attrs['ref'])){ - $this->xdebug("processing element as ref to ".$attrs['ref']); - $this->currentElement = "ref to ".$attrs['ref']; - $ename = $this->getLocalPart($attrs['ref']); - } else { - $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']); - $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type); - $this->currentElement = $attrs['name']; - $attrs['type'] = $this->schemaTargetNamespace . ':' . $type; - $ename = $attrs['name']; - } - if (isset($ename) && $this->currentComplexType) { - $this->xdebug("add element $ename to complexType $this->currentComplexType"); - $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs; - } elseif (!isset($attrs['ref'])) { - $this->xdebug("add element $ename to elements array"); - $this->elements[ $attrs['name'] ] = $attrs; - $this->elements[ $attrs['name'] ]['typeClass'] = 'element'; - } - break; - case 'enumeration': // restriction value list member - $this->xdebug('enumeration ' . $attrs['value']); - if ($this->currentSimpleType) { - $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value']; - } elseif ($this->currentComplexType) { - $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value']; - } - break; - case 'extension': // simpleContent or complexContent type extension - $this->xdebug('extension ' . $attrs['base']); - if ($this->currentComplexType) { - $ns = $this->getPrefix($attrs['base']); - if ($ns == '') { - $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base']; - } else { - $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base']; - } - } else { - $this->xdebug('no current complexType to set extensionBase'); - } - break; - case 'import': - if (isset($attrs['schemaLocation'])) { - $this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']); - $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false); - } else { - $this->xdebug('import namespace ' . $attrs['namespace']); - $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true); - if (! $this->getPrefixFromNamespace($attrs['namespace'])) { - $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace']; - } - } - break; - case 'include': - if (isset($attrs['schemaLocation'])) { - $this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']); - $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false); - } else { - $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute'); - } - break; - case 'list': // simpleType value list - $this->xdebug("do nothing for element $name"); - break; - case 'restriction': // simpleType, simpleContent or complexContent value restriction - $this->xdebug('restriction ' . $attrs['base']); - if($this->currentSimpleType){ - $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base']; - } elseif($this->currentComplexType){ - $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base']; - if(strstr($attrs['base'],':') == ':Array'){ - $this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; - } - } - break; - case 'schema': - $this->schemaInfo = $attrs; - $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix); - if (isset($attrs['targetNamespace'])) { - $this->schemaTargetNamespace = $attrs['targetNamespace']; - } - if (!isset($attrs['elementFormDefault'])) { - $this->schemaInfo['elementFormDefault'] = 'unqualified'; - } - if (!isset($attrs['attributeFormDefault'])) { - $this->schemaInfo['attributeFormDefault'] = 'unqualified'; - } - break; - case 'simpleContent': // (optional) content for a complexType - if ($this->currentComplexType) { // This should *always* be - $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true'; - } else { - $this->xdebug("do nothing for element $name because there is no current complexType"); - } - break; - case 'simpleType': - array_push($this->simpleTypeStack, $this->currentSimpleType); - if(isset($attrs['name'])){ - $this->xdebug("processing simpleType for name " . $attrs['name']); - $this->currentSimpleType = $attrs['name']; - $this->simpleTypes[ $attrs['name'] ] = $attrs; - $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType'; - $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar'; - } else { - $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement); - $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name); - $this->currentSimpleType = $name; - //$this->currentElement = false; - $this->simpleTypes[$this->currentSimpleType] = $attrs; - $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar'; - } - break; - case 'union': // simpleType type list - $this->xdebug("do nothing for element $name"); - break; - default: - $this->xdebug("do not have any logic to process element $name"); - } - } - - /** - * end-element handler - * - * @param string $parser XML parser object - * @param string $name element name - * @access private - */ - function schemaEndElement($parser, $name) { - // bring depth down a notch - $this->depth--; - // position of current element is equal to the last value left in depth_array for my depth - if(isset($this->depth_array[$this->depth])){ - $pos = $this->depth_array[$this->depth]; - } - // get element prefix - if ($prefix = $this->getPrefix($name)){ - // get unqualified name - $name = $this->getLocalPart($name); - } else { - $prefix = ''; - } - // move on... - if($name == 'complexType'){ - $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)')); - $this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType])); - $this->currentComplexType = array_pop($this->complexTypeStack); - //$this->currentElement = false; - } - if($name == 'element'){ - $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)')); - $this->currentElement = array_pop($this->elementStack); - } - if($name == 'simpleType'){ - $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)')); - $this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType])); - $this->currentSimpleType = array_pop($this->simpleTypeStack); - } - } - - /** - * element content handler - * - * @param string $parser XML parser object - * @param string $data element content - * @access private - */ - function schemaCharacterData($parser, $data){ - $pos = $this->depth_array[$this->depth - 1]; - $this->message[$pos]['cdata'] .= $data; - } - - /** - * serialize the schema - * - * @access public - */ - function serializeSchema(){ - - $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion); - $xml = ''; - // imports - if (sizeof($this->imports) > 0) { - foreach($this->imports as $ns => $list) { - foreach ($list as $ii) { - if ($ii['location'] != '') { - $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n"; - } else { - $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n"; - } - } - } - } - // complex types - foreach($this->complexTypes as $typeName => $attrs){ - $contentStr = ''; - // serialize child elements - if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){ - foreach($attrs['elements'] as $element => $eParts){ - if(isset($eParts['ref'])){ - $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n"; - } else { - $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\""; - foreach ($eParts as $aName => $aValue) { - // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable - if ($aName != 'name' && $aName != 'type') { - $contentStr .= " $aName=\"$aValue\""; - } - } - $contentStr .= "/>\n"; - } - } - // compositor wraps elements - if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) { - $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." \n"; - } - } - // attributes - if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){ - foreach($attrs['attrs'] as $attr => $aParts){ - $contentStr .= " <$schemaPrefix:attribute"; - foreach ($aParts as $a => $v) { - if ($a == 'ref' || $a == 'type') { - $contentStr .= " $a=\"".$this->contractQName($v).'"'; - } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') { - $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl']; - $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"'; - } else { - $contentStr .= " $a=\"$v\""; - } - } - $contentStr .= "/>\n"; - } - } - // if restriction - if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){ - $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." \n"; - // complex or simple content - if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){ - $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." \n"; - } - } - // finalize complex type - if($contentStr != ''){ - $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." \n"; - } else { - $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n"; - } - $xml .= $contentStr; - } - // simple types - if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){ - foreach($this->simpleTypes as $typeName => $eParts){ - $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n"; - if (isset($eParts['enumeration'])) { - foreach ($eParts['enumeration'] as $e) { - $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n"; - } - } - $xml .= " \n "; - } - } - // elements - if(isset($this->elements) && count($this->elements) > 0){ - foreach($this->elements as $element => $eParts){ - $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n"; - } - } - // attributes - if(isset($this->attributes) && count($this->attributes) > 0){ - foreach($this->attributes as $attr => $aParts){ - $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>"; - } - } - // finish 'er up - $attr = ''; - foreach ($this->schemaInfo as $k => $v) { - if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') { - $attr .= " $k=\"$v\""; - } - } - $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n"; - foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) { - $el .= " xmlns:$nsp=\"$ns\""; - } - $xml = $el . ">\n".$xml."\n"; - return $xml; - } - - /** - * adds debug data to the clas level debug string - * - * @param string $string debug data - * @access private - */ - function xdebug($string){ - $this->debug('<' . $this->schemaTargetNamespace . '> '.$string); - } - - /** - * get the PHP type of a user defined type in the schema - * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays - * returns false if no type exists, or not w/ the given namespace - * else returns a string that is either a native php type, or 'struct' - * - * @param string $type name of defined type - * @param string $ns namespace of type - * @return mixed - * @access public - * @deprecated - */ - function getPHPType($type,$ns){ - if(isset($this->typemap[$ns][$type])){ - //print "found type '$type' and ns $ns in typemap
    "; - return $this->typemap[$ns][$type]; - } elseif(isset($this->complexTypes[$type])){ - //print "getting type '$type' and ns $ns from complexTypes array
    "; - return $this->complexTypes[$type]['phpType']; - } - return false; - } - - /** - * returns an associative array of information about a given type - * returns false if no type exists by the given name - * - * For a complexType typeDef = array( - * 'restrictionBase' => '', - * 'phpType' => '', - * 'compositor' => '(sequence|all)', - * 'elements' => array(), // refs to elements array - * 'attrs' => array() // refs to attributes array - * ... and so on (see addComplexType) - * ) - * - * For simpleType or element, the array has different keys. - * - * @param string $type - * @return mixed - * @access public - * @see addComplexType - * @see addSimpleType - * @see addElement - */ - function getTypeDef($type){ - //$this->debug("in getTypeDef for type $type"); - if (substr($type, -1) == '^') { - $is_element = 1; - $type = substr($type, 0, -1); - } else { - $is_element = 0; - } - - if((! $is_element) && isset($this->complexTypes[$type])){ - $this->xdebug("in getTypeDef, found complexType $type"); - return $this->complexTypes[$type]; - } elseif((! $is_element) && isset($this->simpleTypes[$type])){ - $this->xdebug("in getTypeDef, found simpleType $type"); - if (!isset($this->simpleTypes[$type]['phpType'])) { - // get info for type to tack onto the simple type - // TODO: can this ever really apply (i.e. what is a simpleType really?) - $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1); - $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':')); - $etype = $this->getTypeDef($uqType); - if ($etype) { - $this->xdebug("in getTypeDef, found type for simpleType $type:"); - $this->xdebug($this->varDump($etype)); - if (isset($etype['phpType'])) { - $this->simpleTypes[$type]['phpType'] = $etype['phpType']; - } - if (isset($etype['elements'])) { - $this->simpleTypes[$type]['elements'] = $etype['elements']; - } - } - } - return $this->simpleTypes[$type]; - } elseif(isset($this->elements[$type])){ - $this->xdebug("in getTypeDef, found element $type"); - if (!isset($this->elements[$type]['phpType'])) { - // get info for type to tack onto the element - $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1); - $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':')); - $etype = $this->getTypeDef($uqType); - if ($etype) { - $this->xdebug("in getTypeDef, found type for element $type:"); - $this->xdebug($this->varDump($etype)); - if (isset($etype['phpType'])) { - $this->elements[$type]['phpType'] = $etype['phpType']; - } - if (isset($etype['elements'])) { - $this->elements[$type]['elements'] = $etype['elements']; - } - if (isset($etype['extensionBase'])) { - $this->elements[$type]['extensionBase'] = $etype['extensionBase']; - } - } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') { - $this->xdebug("in getTypeDef, element $type is an XSD type"); - $this->elements[$type]['phpType'] = 'scalar'; - } - } - return $this->elements[$type]; - } elseif(isset($this->attributes[$type])){ - $this->xdebug("in getTypeDef, found attribute $type"); - return $this->attributes[$type]; - } elseif (preg_match('/_ContainedType$/', $type)) { - $this->xdebug("in getTypeDef, have an untyped element $type"); - $typeDef['typeClass'] = 'simpleType'; - $typeDef['phpType'] = 'scalar'; - $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string'; - return $typeDef; - } - $this->xdebug("in getTypeDef, did not find $type"); - return false; - } - - /** - * returns a sample serialization of a given type, or false if no type by the given name - * - * @param string $type name of type - * @return mixed - * @access public - * @deprecated - */ - function serializeTypeDef($type){ - //print "in sTD() for type $type
    "; - if($typeDef = $this->getTypeDef($type)){ - $str .= '<'.$type; - if(is_array($typeDef['attrs'])){ - foreach($typeDef['attrs'] as $attName => $data){ - $str .= " $attName=\"{type = ".$data['type']."}\""; - } - } - $str .= " xmlns=\"".$this->schema['targetNamespace']."\""; - if(count($typeDef['elements']) > 0){ - $str .= ">"; - foreach($typeDef['elements'] as $element => $eData){ - $str .= $this->serializeTypeDef($element); - } - $str .= ""; - } elseif($typeDef['typeClass'] == 'element') { - $str .= ">"; - } else { - $str .= "/>"; - } - return $str; - } - return false; - } - - /** - * returns HTML form elements that allow a user - * to enter values for creating an instance of the given type. - * - * @param string $name name for type instance - * @param string $type name of type - * @return string - * @access public - * @deprecated - */ - function typeToForm($name,$type){ - // get typedef - if($typeDef = $this->getTypeDef($type)){ - // if struct - if($typeDef['phpType'] == 'struct'){ - $buffer .= ''; - foreach($typeDef['elements'] as $child => $childDef){ - $buffer .= " - - "; - } - $buffer .= '
    $childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):
    '; - // if array - } elseif($typeDef['phpType'] == 'array'){ - $buffer .= ''; - for($i=0;$i < 3; $i++){ - $buffer .= " - - "; - } - $buffer .= '
    array item (type: $typeDef[arrayType]):
    '; - // if scalar - } else { - $buffer .= ""; - } - } else { - $buffer .= ""; - } - return $buffer; - } - - /** - * adds a complex type to the schema - * - * example: array - * - * addType( - * 'ArrayOfstring', - * 'complexType', - * 'array', - * '', - * 'SOAP-ENC:Array', - * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'), - * 'xsd:string' - * ); - * - * example: PHP associative array ( SOAP Struct ) - * - * addType( - * 'SOAPStruct', - * 'complexType', - * 'struct', - * 'all', - * array('myVar'=> array('name'=>'myVar','type'=>'string') - * ); - * - * @param name - * @param typeClass (complexType|simpleType|attribute) - * @param phpType: currently supported are array and struct (php assoc array) - * @param compositor (all|sequence|choice) - * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param elements = array ( name = array(name=>'',type=>'') ) - * @param attrs = array( - * array( - * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType", - * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]" - * ) - * ) - * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string) - * @access public - * @see getTypeDef - */ - function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){ - $this->complexTypes[$name] = array( - 'name' => $name, - 'typeClass' => $typeClass, - 'phpType' => $phpType, - 'compositor'=> $compositor, - 'restrictionBase' => $restrictionBase, - 'elements' => $elements, - 'attrs' => $attrs, - 'arrayType' => $arrayType - ); - - $this->xdebug("addComplexType $name:"); - $this->appendDebug($this->varDump($this->complexTypes[$name])); - } - - /** - * adds a simple type to the schema - * - * @param string $name - * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param string $typeClass (should always be simpleType) - * @param string $phpType (should always be scalar) - * @param array $enumeration array of values - * @access public - * @see nusoap_xmlschema - * @see getTypeDef - */ - function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) { - $this->simpleTypes[$name] = array( - 'name' => $name, - 'typeClass' => $typeClass, - 'phpType' => $phpType, - 'type' => $restrictionBase, - 'enumeration' => $enumeration - ); - - $this->xdebug("addSimpleType $name:"); - $this->appendDebug($this->varDump($this->simpleTypes[$name])); - } - - /** - * adds an element to the schema - * - * @param array $attrs attributes that must include name and type - * @see nusoap_xmlschema - * @access public - */ - function addElement($attrs) { - if (! $this->getPrefix($attrs['type'])) { - $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type']; - } - $this->elements[ $attrs['name'] ] = $attrs; - $this->elements[ $attrs['name'] ]['typeClass'] = 'element'; - - $this->xdebug("addElement " . $attrs['name']); - $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ])); - } -} - -/** - * Backward compatibility - */ -class XMLSchema extends nusoap_xmlschema { -} - -?> -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class soapval extends nusoap_base { - /** - * The XML element name - * - * @var string - * @access private - */ - var $name; - /** - * The XML type name (string or false) - * - * @var mixed - * @access private - */ - var $type; - /** - * The PHP value - * - * @var mixed - * @access private - */ - var $value; - /** - * The XML element namespace (string or false) - * - * @var mixed - * @access private - */ - var $element_ns; - /** - * The XML type namespace (string or false) - * - * @var mixed - * @access private - */ - var $type_ns; - /** - * The XML element attributes (array or false) - * - * @var mixed - * @access private - */ - var $attributes; - - /** - * constructor - * - * @param string $name optional name - * @param mixed $type optional type name - * @param mixed $value optional value - * @param mixed $element_ns optional namespace of value - * @param mixed $type_ns optional namespace of type - * @param mixed $attributes associative array of attributes to add to element serialization - * @access public - */ - function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) { - parent::nusoap_base(); - $this->name = $name; - $this->type = $type; - $this->value = $value; - $this->element_ns = $element_ns; - $this->type_ns = $type_ns; - $this->attributes = $attributes; - } - - /** - * return serialized value - * - * @param string $use The WSDL use value (encoded|literal) - * @return string XML data - * @access public - */ - function serialize($use='encoded') { - return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true); - } - - /** - * decodes a soapval object into a PHP native type - * - * @return mixed - * @access public - */ - function decode(){ - return $this->value; - } -} - - - -?> -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class soap_transport_http extends nusoap_base { - - var $url = ''; - var $uri = ''; - var $digest_uri = ''; - var $scheme = ''; - var $host = ''; - var $port = ''; - var $path = ''; - var $request_method = 'POST'; - var $protocol_version = '1.0'; - var $encoding = ''; - var $outgoing_headers = array(); - var $incoming_headers = array(); - var $incoming_cookies = array(); - var $outgoing_payload = ''; - var $incoming_payload = ''; - var $response_status_line; // HTTP response status line - var $useSOAPAction = true; - var $persistentConnection = false; - var $ch = false; // cURL handle - var $ch_options = array(); // cURL custom options - var $use_curl = false; // force cURL use - var $proxy = null; // proxy information (associative array) - var $username = ''; - var $password = ''; - var $authtype = ''; - var $digestRequest = array(); - var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional) - // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem' - // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem' - // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem' - // passphrase: SSL key password/passphrase - // certpassword: SSL certificate password - // verifypeer: default is 1 - // verifyhost: default is 1 - - /** - * constructor - * - * @param string $url The URL to which to connect - * @param array $curl_options User-specified cURL options - * @param boolean $use_curl Whether to try to force cURL use - * @access public - */ - function soap_transport_http($url, $curl_options = NULL, $use_curl = false){ - parent::nusoap_base(); - $this->debug("ctor url=$url use_curl=$use_curl curl_options:"); - $this->appendDebug($this->varDump($curl_options)); - $this->setURL($url); - if (is_array($curl_options)) { - $this->ch_options = $curl_options; - } - $this->use_curl = $use_curl; - preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev); - $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')'); - } - - /** - * sets a cURL option - * - * @param mixed $option The cURL option (always integer?) - * @param mixed $value The cURL option value - * @access private - */ - function setCurlOption($option, $value) { - $this->debug("setCurlOption option=$option, value="); - $this->appendDebug($this->varDump($value)); - curl_setopt($this->ch, $option, $value); - } - - /** - * sets an HTTP header - * - * @param string $name The name of the header - * @param string $value The value of the header - * @access private - */ - function setHeader($name, $value) { - $this->outgoing_headers[$name] = $value; - $this->debug("set header $name: $value"); - } - - /** - * unsets an HTTP header - * - * @param string $name The name of the header - * @access private - */ - function unsetHeader($name) { - if (isset($this->outgoing_headers[$name])) { - $this->debug("unset header $name"); - unset($this->outgoing_headers[$name]); - } - } - - /** - * sets the URL to which to connect - * - * @param string $url The URL to which to connect - * @access private - */ - function setURL($url) { - $this->url = $url; - - $u = parse_url($url); - foreach($u as $k => $v){ - $this->debug("parsed URL $k = $v"); - $this->$k = $v; - } - - // add any GET params to path - if(isset($u['query']) && $u['query'] != ''){ - $this->path .= '?' . $u['query']; - } - - // set default port - if(!isset($u['port'])){ - if($u['scheme'] == 'https'){ - $this->port = 443; - } else { - $this->port = 80; - } - } - - $this->uri = $this->path; - $this->digest_uri = $this->uri; - - // build headers - if (!isset($u['port'])) { - $this->setHeader('Host', $this->host); - } else { - $this->setHeader('Host', $this->host.':'.$this->port); - } - - if (isset($u['user']) && $u['user'] != '') { - $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : ''); - } - } - - /** - * gets the I/O method to use - * - * @return string I/O method to use (socket|curl|unknown) - * @access private - */ - function io_method() { - if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm')) - return 'curl'; - if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm')) - return 'socket'; - return 'unknown'; - } - - /** - * establish an HTTP connection - * - * @param integer $timeout set connection timeout in seconds - * @param integer $response_timeout set response timeout in seconds - * @return boolean true if connected, false if not - * @access private - */ - function connect($connection_timeout=0,$response_timeout=30){ - // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like - // "regular" socket. - // TODO: disabled for now because OpenSSL must be *compiled* in (not just - // loaded), and until PHP5 stream_get_wrappers is not available. -// if ($this->scheme == 'https') { -// if (version_compare(phpversion(), '4.3.0') >= 0) { -// if (extension_loaded('openssl')) { -// $this->scheme = 'ssl'; -// $this->debug('Using SSL over OpenSSL'); -// } -// } -// } - $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port"); - if ($this->io_method() == 'socket') { - if (!is_array($this->proxy)) { - $host = $this->host; - $port = $this->port; - } else { - $host = $this->proxy['host']; - $port = $this->proxy['port']; - } - - // use persistent connection - if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){ - if (!feof($this->fp)) { - $this->debug('Re-use persistent connection'); - return true; - } - fclose($this->fp); - $this->debug('Closed persistent connection at EOF'); - } - - // munge host if using OpenSSL - if ($this->scheme == 'ssl') { - $host = 'ssl://' . $host; - } - $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout); - - // open socket - if($connection_timeout > 0){ - $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout); - } else { - $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str); - } - - // test pointer - if(!$this->fp) { - $msg = 'Couldn\'t open socket connection to server ' . $this->url; - if ($this->errno) { - $msg .= ', Error ('.$this->errno.'): '.$this->error_str; - } else { - $msg .= ' prior to connect(). This is often a problem looking up the host name.'; - } - $this->debug($msg); - $this->setError($msg); - return false; - } - - // set response timeout - $this->debug('set response timeout to ' . $response_timeout); - socket_set_timeout( $this->fp, $response_timeout); - - $this->debug('socket connected'); - return true; - } else if ($this->io_method() == 'curl') { - if (!extension_loaded('curl')) { -// $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS'); - $this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to include cURL or change php.ini to load the PHP cURL extension.'); - return false; - } - // Avoid warnings when PHP does not have these options - if (defined('CURLOPT_CONNECTIONTIMEOUT')) - $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT; - else - $CURLOPT_CONNECTIONTIMEOUT = 78; - if (defined('CURLOPT_HTTPAUTH')) - $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH; - else - $CURLOPT_HTTPAUTH = 107; - if (defined('CURLOPT_PROXYAUTH')) - $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH; - else - $CURLOPT_PROXYAUTH = 111; - if (defined('CURLAUTH_BASIC')) - $CURLAUTH_BASIC = CURLAUTH_BASIC; - else - $CURLAUTH_BASIC = 1; - if (defined('CURLAUTH_DIGEST')) - $CURLAUTH_DIGEST = CURLAUTH_DIGEST; - else - $CURLAUTH_DIGEST = 2; - if (defined('CURLAUTH_NTLM')) - $CURLAUTH_NTLM = CURLAUTH_NTLM; - else - $CURLAUTH_NTLM = 8; - - $this->debug('connect using cURL'); - // init CURL - $this->ch = curl_init(); - // set url - $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host"; - // add path - $hostURL .= $this->path; - $this->setCurlOption(CURLOPT_URL, $hostURL); - // follow location headers (re-directs) - if (ini_get('safe_mode') || ini_get('open_basedir')) { - $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION'); - $this->debug('safe_mode = '); - $this->appendDebug($this->varDump(ini_get('safe_mode'))); - $this->debug('open_basedir = '); - $this->appendDebug($this->varDump(ini_get('open_basedir'))); - } else { - $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1); - } - // ask for headers in the response output - $this->setCurlOption(CURLOPT_HEADER, 1); - // ask for the response output as the return value - $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1); - // encode - // We manage this ourselves through headers and encoding -// if(function_exists('gzuncompress')){ -// $this->setCurlOption(CURLOPT_ENCODING, 'deflate'); -// } - // persistent connection - if ($this->persistentConnection) { - // I believe the following comment is now bogus, having applied to - // the code when it used CURLOPT_CUSTOMREQUEST to send the request. - // The way we send data, we cannot use persistent connections, since - // there will be some "junk" at the end of our request. - //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true); - $this->persistentConnection = false; - $this->setHeader('Connection', 'close'); - } - // set timeouts - if ($connection_timeout != 0) { - $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout); - } - if ($response_timeout != 0) { - $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout); - } - - if ($this->scheme == 'https') { - $this->debug('set cURL SSL verify options'); - // recent versions of cURL turn on peer/host checking by default, - // while PHP binaries are not compiled with a default location for the - // CA cert bundle, so disable peer/host checking. - //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt'); - $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0); - $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0); - - // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo) - if ($this->authtype == 'certificate') { - $this->debug('set cURL certificate options'); - if (isset($this->certRequest['cainfofile'])) { - $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']); - } - if (isset($this->certRequest['verifypeer'])) { - $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']); - } else { - $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1); - } - if (isset($this->certRequest['verifyhost'])) { - $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']); - } else { - $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1); - } - if (isset($this->certRequest['sslcertfile'])) { - $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']); - } - if (isset($this->certRequest['sslkeyfile'])) { - $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']); - } - if (isset($this->certRequest['passphrase'])) { - $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']); - } - if (isset($this->certRequest['certpassword'])) { - $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']); - } - } - } - if ($this->authtype && ($this->authtype != 'certificate')) { - if ($this->username) { - $this->debug('set cURL username/password'); - $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password"); - } - if ($this->authtype == 'basic') { - $this->debug('set cURL for Basic authentication'); - $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC); - } - if ($this->authtype == 'digest') { - $this->debug('set cURL for digest authentication'); - $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST); - } - if ($this->authtype == 'ntlm') { - $this->debug('set cURL for NTLM authentication'); - $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM); - } - } - if (is_array($this->proxy)) { - $this->debug('set cURL proxy options'); - if ($this->proxy['port'] != '') { - $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']); - } else { - $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']); - } - if ($this->proxy['username'] || $this->proxy['password']) { - $this->debug('set cURL proxy authentication options'); - $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']); - if ($this->proxy['authtype'] == 'basic') { - $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC); - } - if ($this->proxy['authtype'] == 'ntlm') { - $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM); - } - } - } - $this->debug('cURL connection set up'); - return true; - } else { - $this->setError('Unknown scheme ' . $this->scheme); - $this->debug('Unknown scheme ' . $this->scheme); - return false; - } - } - - /** - * sends the SOAP request and gets the SOAP response via HTTP[S] - * - * @param string $data message data - * @param integer $timeout set connection timeout in seconds - * @param integer $response_timeout set response timeout in seconds - * @param array $cookies cookies to send - * @return string data - * @access public - */ - function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) { - - $this->debug('entered send() with data of length: '.strlen($data)); - - $this->tryagain = true; - $tries = 0; - while ($this->tryagain) { - $this->tryagain = false; - if ($tries++ < 2) { - // make connnection - if (!$this->connect($timeout, $response_timeout)){ - return false; - } - - // send request - if (!$this->sendRequest($data, $cookies)){ - return false; - } - - // get response - $respdata = $this->getResponse(); - } else { - $this->setError("Too many tries to get an OK response ($this->response_status_line)"); - } - } - $this->debug('end of send()'); - return $respdata; - } - - - /** - * sends the SOAP request and gets the SOAP response via HTTPS using CURL - * - * @param string $data message data - * @param integer $timeout set connection timeout in seconds - * @param integer $response_timeout set response timeout in seconds - * @param array $cookies cookies to send - * @return string data - * @access public - * @deprecated - */ - function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) { - return $this->send($data, $timeout, $response_timeout, $cookies); - } - - /** - * if authenticating, set user credentials here - * - * @param string $username - * @param string $password - * @param string $authtype (basic|digest|certificate|ntlm) - * @param array $digestRequest (keys must be nonce, nc, realm, qop) - * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) - * @access public - */ - function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) { - $this->debug("setCredentials username=$username authtype=$authtype digestRequest="); - $this->appendDebug($this->varDump($digestRequest)); - $this->debug("certRequest="); - $this->appendDebug($this->varDump($certRequest)); - // cf. RFC 2617 - if ($authtype == 'basic') { - $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password)); - } elseif ($authtype == 'digest') { - if (isset($digestRequest['nonce'])) { - $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1; - - // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html) - - // A1 = unq(username-value) ":" unq(realm-value) ":" passwd - $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password; - - // H(A1) = MD5(A1) - $HA1 = md5($A1); - - // A2 = Method ":" digest-uri-value - $A2 = $this->request_method . ':' . $this->digest_uri; - - // H(A2) - $HA2 = md5($A2); - - // KD(secret, data) = H(concat(secret, ":", data)) - // if qop == auth: - // request-digest = <"> < KD ( H(A1), unq(nonce-value) - // ":" nc-value - // ":" unq(cnonce-value) - // ":" unq(qop-value) - // ":" H(A2) - // ) <"> - // if qop is missing, - // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <"> - - $unhashedDigest = ''; - $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : ''; - $cnonce = $nonce; - if ($digestRequest['qop'] != '') { - $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2; - } else { - $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2; - } - - $hashedDigest = md5($unhashedDigest); - - $opaque = ''; - if (isset($digestRequest['opaque'])) { - $opaque = ', opaque="' . $digestRequest['opaque'] . '"'; - } - - $this->setHeader('Authorization', 'Digest username="' . $username . '", realm="' . $digestRequest['realm'] . '", nonce="' . $nonce . '", uri="' . $this->digest_uri . $opaque . '", cnonce="' . $cnonce . '", nc=' . sprintf("%08x", $digestRequest['nc']) . ', qop="' . $digestRequest['qop'] . '", response="' . $hashedDigest . '"'); - } - } elseif ($authtype == 'certificate') { - $this->certRequest = $certRequest; - $this->debug('Authorization header not set for certificate'); - } elseif ($authtype == 'ntlm') { - // do nothing - $this->debug('Authorization header not set for ntlm'); - } - $this->username = $username; - $this->password = $password; - $this->authtype = $authtype; - $this->digestRequest = $digestRequest; - } - - /** - * set the soapaction value - * - * @param string $soapaction - * @access public - */ - function setSOAPAction($soapaction) { - $this->setHeader('SOAPAction', '"' . $soapaction . '"'); - } - - /** - * use http encoding - * - * @param string $enc encoding style. supported values: gzip, deflate, or both - * @access public - */ - function setEncoding($enc='gzip, deflate') { - if (function_exists('gzdeflate')) { - $this->protocol_version = '1.1'; - $this->setHeader('Accept-Encoding', $enc); - if (!isset($this->outgoing_headers['Connection'])) { - $this->setHeader('Connection', 'close'); - $this->persistentConnection = false; - } - // deprecated as of PHP 5.3.0 - //set_magic_quotes_runtime(0); - $this->encoding = $enc; - } - } - - /** - * set proxy info here - * - * @param string $proxyhost use an empty string to remove proxy - * @param string $proxyport - * @param string $proxyusername - * @param string $proxypassword - * @param string $proxyauthtype (basic|ntlm) - * @access public - */ - function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') { - if ($proxyhost) { - $this->proxy = array( - 'host' => $proxyhost, - 'port' => $proxyport, - 'username' => $proxyusername, - 'password' => $proxypassword, - 'authtype' => $proxyauthtype - ); - if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') { - $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword)); - } - } else { - $this->debug('remove proxy'); - $proxy = null; - unsetHeader('Proxy-Authorization'); - } - } - - - /** - * Test if the given string starts with a header that is to be skipped. - * Skippable headers result from chunked transfer and proxy requests. - * - * @param string $data The string to check. - * @returns boolean Whether a skippable header was found. - * @access private - */ - function isSkippableCurlHeader(&$data) { - $skipHeaders = array( 'HTTP/1.1 100', - 'HTTP/1.0 301', - 'HTTP/1.1 301', - 'HTTP/1.0 302', - 'HTTP/1.1 302', - 'HTTP/1.0 401', - 'HTTP/1.1 401', - 'HTTP/1.0 200 Connection established'); - foreach ($skipHeaders as $hd) { - $prefix = substr($data, 0, strlen($hd)); - if ($prefix == $hd) return true; - } - - return false; - } - - /** - * decode a string that is encoded w/ "chunked' transfer encoding - * as defined in RFC2068 19.4.6 - * - * @param string $buffer - * @param string $lb - * @returns string - * @access public - * @deprecated - */ - function decodeChunked($buffer, $lb){ - // length := 0 - $length = 0; - $new = ''; - - // read chunk-size, chunk-extension (if any) and CRLF - // get the position of the linebreak - $chunkend = strpos($buffer, $lb); - if ($chunkend == FALSE) { - $this->debug('no linebreak found in decodeChunked'); - return $new; - } - $temp = substr($buffer,0,$chunkend); - $chunk_size = hexdec( trim($temp) ); - $chunkstart = $chunkend + strlen($lb); - // while (chunk-size > 0) { - while ($chunk_size > 0) { - $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size"); - $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size); - - // Just in case we got a broken connection - if ($chunkend == FALSE) { - $chunk = substr($buffer,$chunkstart); - // append chunk-data to entity-body - $new .= $chunk; - $length += strlen($chunk); - break; - } - - // read chunk-data and CRLF - $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart); - // append chunk-data to entity-body - $new .= $chunk; - // length := length + chunk-size - $length += strlen($chunk); - // read chunk-size and CRLF - $chunkstart = $chunkend + strlen($lb); - - $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb); - if ($chunkend == FALSE) { - break; //Just in case we got a broken connection - } - $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart); - $chunk_size = hexdec( trim($temp) ); - $chunkstart = $chunkend; - } - return $new; - } - - /** - * Writes the payload, including HTTP headers, to $this->outgoing_payload. - * - * @param string $data HTTP body - * @param string $cookie_str data for HTTP Cookie header - * @return void - * @access private - */ - function buildPayload($data, $cookie_str = '') { - // Note: for cURL connections, $this->outgoing_payload is ignored, - // as is the Content-Length header, but these are still created as - // debugging guides. - - // add content-length header - if ($this->request_method != 'GET') { - $this->setHeader('Content-Length', strlen($data)); - } - - // start building outgoing payload: - if ($this->proxy) { - $uri = $this->url; - } else { - $uri = $this->uri; - } - $req = "$this->request_method $uri HTTP/$this->protocol_version"; - $this->debug("HTTP request: $req"); - $this->outgoing_payload = "$req\r\n"; - - // loop thru headers, serializing - foreach($this->outgoing_headers as $k => $v){ - $hdr = $k.': '.$v; - $this->debug("HTTP header: $hdr"); - $this->outgoing_payload .= "$hdr\r\n"; - } - - // add any cookies - if ($cookie_str != '') { - $hdr = 'Cookie: '.$cookie_str; - $this->debug("HTTP header: $hdr"); - $this->outgoing_payload .= "$hdr\r\n"; - } - - // header/body separator - $this->outgoing_payload .= "\r\n"; - - // add data - $this->outgoing_payload .= $data; - } - - /** - * sends the SOAP request via HTTP[S] - * - * @param string $data message data - * @param array $cookies cookies to send - * @return boolean true if OK, false if problem - * @access private - */ - function sendRequest($data, $cookies = NULL) { - // build cookie string - $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https'))); - - // build payload - $this->buildPayload($data, $cookie_str); - - if ($this->io_method() == 'socket') { - // send payload - if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) { - $this->setError('couldn\'t write message data to socket'); - $this->debug('couldn\'t write message data to socket'); - return false; - } - $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload)); - return true; - } else if ($this->io_method() == 'curl') { - // set payload - // cURL does say this should only be the verb, and in fact it - // turns out that the URI and HTTP version are appended to this, which - // some servers refuse to work with (so we no longer use this method!) - //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload); - $curl_headers = array(); - foreach($this->outgoing_headers as $k => $v){ - if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') { - $this->debug("Skip cURL header $k: $v"); - } else { - $curl_headers[] = "$k: $v"; - } - } - if ($cookie_str != '') { - $curl_headers[] = 'Cookie: ' . $cookie_str; - } - $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers); - $this->debug('set cURL HTTP headers'); - if ($this->request_method == "POST") { - $this->setCurlOption(CURLOPT_POST, 1); - $this->setCurlOption(CURLOPT_POSTFIELDS, $data); - $this->debug('set cURL POST data'); - } else { - } - // insert custom user-set cURL options - foreach ($this->ch_options as $key => $val) { - $this->setCurlOption($key, $val); - } - - $this->debug('set cURL payload'); - return true; - } - } - - /** - * gets the SOAP response via HTTP[S] - * - * @return string the response (also sets member variables like incoming_payload) - * @access private - */ - function getResponse(){ - $this->incoming_payload = ''; - - if ($this->io_method() == 'socket') { - // loop until headers have been retrieved - $data = ''; - while (!isset($lb)){ - - // We might EOF during header read. - if(feof($this->fp)) { - $this->incoming_payload = $data; - $this->debug('found no headers before EOF after length ' . strlen($data)); - $this->debug("received before EOF:\n" . $data); - $this->setError('server failed to send headers'); - return false; - } - - $tmp = fgets($this->fp, 256); - $tmplen = strlen($tmp); - $this->debug("read line of $tmplen bytes: " . trim($tmp)); - - if ($tmplen == 0) { - $this->incoming_payload = $data; - $this->debug('socket read of headers timed out after length ' . strlen($data)); - $this->debug("read before timeout: " . $data); - $this->setError('socket read of headers timed out'); - return false; - } - - $data .= $tmp; - $pos = strpos($data,"\r\n\r\n"); - if($pos > 1){ - $lb = "\r\n"; - } else { - $pos = strpos($data,"\n\n"); - if($pos > 1){ - $lb = "\n"; - } - } - // remove 100 headers - if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) { - unset($lb); - $data = ''; - }// - } - // store header data - $this->incoming_payload .= $data; - $this->debug('found end of headers after length ' . strlen($data)); - // process headers - $header_data = trim(substr($data,0,$pos)); - $header_array = explode($lb,$header_data); - $this->incoming_headers = array(); - $this->incoming_cookies = array(); - foreach($header_array as $header_line){ - $arr = explode(':',$header_line, 2); - if(count($arr) > 1){ - $header_name = strtolower(trim($arr[0])); - $this->incoming_headers[$header_name] = trim($arr[1]); - if ($header_name == 'set-cookie') { - // TODO: allow multiple cookies from parseCookie - $cookie = $this->parseCookie(trim($arr[1])); - if ($cookie) { - $this->incoming_cookies[] = $cookie; - $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']); - } else { - $this->debug('did not find cookie in ' . trim($arr[1])); - } - } - } else if (isset($header_name)) { - // append continuation line to previous header - $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line; - } - } - - // loop until msg has been received - if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') { - $content_length = 2147483647; // ignore any content-length header - $chunked = true; - $this->debug("want to read chunked content"); - } elseif (isset($this->incoming_headers['content-length'])) { - $content_length = $this->incoming_headers['content-length']; - $chunked = false; - $this->debug("want to read content of length $content_length"); - } else { - $content_length = 2147483647; - $chunked = false; - $this->debug("want to read content to EOF"); - } - $data = ''; - do { - if ($chunked) { - $tmp = fgets($this->fp, 256); - $tmplen = strlen($tmp); - $this->debug("read chunk line of $tmplen bytes"); - if ($tmplen == 0) { - $this->incoming_payload = $data; - $this->debug('socket read of chunk length timed out after length ' . strlen($data)); - $this->debug("read before timeout:\n" . $data); - $this->setError('socket read of chunk length timed out'); - return false; - } - $content_length = hexdec(trim($tmp)); - $this->debug("chunk length $content_length"); - } - $strlen = 0; - while (($strlen < $content_length) && (!feof($this->fp))) { - $readlen = min(8192, $content_length - $strlen); - $tmp = fread($this->fp, $readlen); - $tmplen = strlen($tmp); - $this->debug("read buffer of $tmplen bytes"); - if (($tmplen == 0) && (!feof($this->fp))) { - $this->incoming_payload = $data; - $this->debug('socket read of body timed out after length ' . strlen($data)); - $this->debug("read before timeout:\n" . $data); - $this->setError('socket read of body timed out'); - return false; - } - $strlen += $tmplen; - $data .= $tmp; - } - if ($chunked && ($content_length > 0)) { - $tmp = fgets($this->fp, 256); - $tmplen = strlen($tmp); - $this->debug("read chunk terminator of $tmplen bytes"); - if ($tmplen == 0) { - $this->incoming_payload = $data; - $this->debug('socket read of chunk terminator timed out after length ' . strlen($data)); - $this->debug("read before timeout:\n" . $data); - $this->setError('socket read of chunk terminator timed out'); - return false; - } - } - } while ($chunked && ($content_length > 0) && (!feof($this->fp))); - if (feof($this->fp)) { - $this->debug('read to EOF'); - } - $this->debug('read body of length ' . strlen($data)); - $this->incoming_payload .= $data; - $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server'); - - // close filepointer - if( - (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') || - (! $this->persistentConnection) || feof($this->fp)){ - fclose($this->fp); - $this->fp = false; - $this->debug('closed socket'); - } - - // connection was closed unexpectedly - if($this->incoming_payload == ''){ - $this->setError('no response from server'); - return false; - } - - // decode transfer-encoding -// if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){ -// if(!$data = $this->decodeChunked($data, $lb)){ -// $this->setError('Decoding of chunked data failed'); -// return false; -// } - //print "
    \nde-chunked:\n---------------\n$data\n\n---------------\n
    "; - // set decoded payload -// $this->incoming_payload = $header_data.$lb.$lb.$data; -// } - - } else if ($this->io_method() == 'curl') { - // send and receive - $this->debug('send and receive with cURL'); - $this->incoming_payload = curl_exec($this->ch); - $data = $this->incoming_payload; - - $cErr = curl_error($this->ch); - if ($cErr != '') { - $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'
    '; - // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE - foreach(curl_getinfo($this->ch) as $k => $v){ - $err .= "$k: $v
    "; - } - $this->debug($err); - $this->setError($err); - curl_close($this->ch); - return false; - } else { - //echo '
    ';
    -			//var_dump(curl_getinfo($this->ch));
    -			//echo '
    '; - } - // close curl - $this->debug('No cURL error, closing cURL'); - curl_close($this->ch); - - // try removing skippable headers - $savedata = $data; - while ($this->isSkippableCurlHeader($data)) { - $this->debug("Found HTTP header to skip"); - if ($pos = strpos($data,"\r\n\r\n")) { - $data = ltrim(substr($data,$pos)); - } elseif($pos = strpos($data,"\n\n") ) { - $data = ltrim(substr($data,$pos)); - } - } - - if ($data == '') { - // have nothing left; just remove 100 header(s) - $data = $savedata; - while (preg_match('/^HTTP\/1.1 100/',$data)) { - if ($pos = strpos($data,"\r\n\r\n")) { - $data = ltrim(substr($data,$pos)); - } elseif($pos = strpos($data,"\n\n") ) { - $data = ltrim(substr($data,$pos)); - } - } - } - - // separate content from HTTP headers - if ($pos = strpos($data,"\r\n\r\n")) { - $lb = "\r\n"; - } elseif( $pos = strpos($data,"\n\n")) { - $lb = "\n"; - } else { - $this->debug('no proper separation of headers and document'); - $this->setError('no proper separation of headers and document'); - return false; - } - $header_data = trim(substr($data,0,$pos)); - $header_array = explode($lb,$header_data); - $data = ltrim(substr($data,$pos)); - $this->debug('found proper separation of headers and document'); - $this->debug('cleaned data, stringlen: '.strlen($data)); - // clean headers - foreach ($header_array as $header_line) { - $arr = explode(':',$header_line,2); - if(count($arr) > 1){ - $header_name = strtolower(trim($arr[0])); - $this->incoming_headers[$header_name] = trim($arr[1]); - if ($header_name == 'set-cookie') { - // TODO: allow multiple cookies from parseCookie - $cookie = $this->parseCookie(trim($arr[1])); - if ($cookie) { - $this->incoming_cookies[] = $cookie; - $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']); - } else { - $this->debug('did not find cookie in ' . trim($arr[1])); - } - } - } else if (isset($header_name)) { - // append continuation line to previous header - $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line; - } - } - } - - $this->response_status_line = $header_array[0]; - $arr = explode(' ', $this->response_status_line, 3); - $http_version = $arr[0]; - $http_status = intval($arr[1]); - $http_reason = count($arr) > 2 ? $arr[2] : ''; - - // see if we need to resend the request with http digest authentication - if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) { - $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']); - $this->setURL($this->incoming_headers['location']); - $this->tryagain = true; - return false; - } - - // see if we need to resend the request with http digest authentication - if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) { - $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']); - if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) { - $this->debug('Server wants digest authentication'); - // remove "Digest " from our elements - $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']); - - // parse elements into array - $digestElements = explode(',', $digestString); - foreach ($digestElements as $val) { - $tempElement = explode('=', trim($val), 2); - $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]); - } - - // should have (at least) qop, realm, nonce - if (isset($digestRequest['nonce'])) { - $this->setCredentials($this->username, $this->password, 'digest', $digestRequest); - $this->tryagain = true; - return false; - } - } - $this->debug('HTTP authentication failed'); - $this->setError('HTTP authentication failed'); - return false; - } - - if ( - ($http_status >= 300 && $http_status <= 307) || - ($http_status >= 400 && $http_status <= 417) || - ($http_status >= 501 && $http_status <= 505) - ) { - $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)"); - return false; - } - - // decode content-encoding - if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){ - if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){ - // if decoding works, use it. else assume data wasn't gzencoded - if(function_exists('gzinflate')){ - //$timer->setMarker('starting decoding of gzip/deflated content'); - // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress) - // this means there are no Zlib headers, although there should be - $this->debug('The gzinflate function exists'); - $datalen = strlen($data); - if ($this->incoming_headers['content-encoding'] == 'deflate') { - if ($degzdata = @gzinflate($data)) { - $data = $degzdata; - $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes'); - if (strlen($data) < $datalen) { - // test for the case that the payload has been compressed twice - $this->debug('The inflated payload is smaller than the gzipped one; try again'); - if ($degzdata = @gzinflate($data)) { - $data = $degzdata; - $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes'); - } - } - } else { - $this->debug('Error using gzinflate to inflate the payload'); - $this->setError('Error using gzinflate to inflate the payload'); - } - } elseif ($this->incoming_headers['content-encoding'] == 'gzip') { - if ($degzdata = @gzinflate(substr($data, 10))) { // do our best - $data = $degzdata; - $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes'); - if (strlen($data) < $datalen) { - // test for the case that the payload has been compressed twice - $this->debug('The un-gzipped payload is smaller than the gzipped one; try again'); - if ($degzdata = @gzinflate(substr($data, 10))) { - $data = $degzdata; - $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes'); - } - } - } else { - $this->debug('Error using gzinflate to un-gzip the payload'); - $this->setError('Error using gzinflate to un-gzip the payload'); - } - } - //$timer->setMarker('finished decoding of gzip/deflated content'); - //print "\nde-inflated:\n---------------\n$data\n-------------\n"; - // set decoded payload - $this->incoming_payload = $header_data.$lb.$lb.$data; - } else { - $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.'); - $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.'); - } - } else { - $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']); - $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']); - } - } else { - $this->debug('No Content-Encoding header'); - } - - if(strlen($data) == 0){ - $this->debug('no data after headers!'); - $this->setError('no data present after HTTP headers'); - return false; - } - - return $data; - } - - /** - * sets the content-type for the SOAP message to be sent - * - * @param string $type the content type, MIME style - * @param mixed $charset character set used for encoding (or false) - * @access public - */ - function setContentType($type, $charset = false) { - $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : '')); - } - - /** - * specifies that an HTTP persistent connection should be used - * - * @return boolean whether the request was honored by this method. - * @access public - */ - function usePersistentConnection(){ - if (isset($this->outgoing_headers['Accept-Encoding'])) { - return false; - } - $this->protocol_version = '1.1'; - $this->persistentConnection = true; - $this->setHeader('Connection', 'Keep-Alive'); - return true; - } - - /** - * parse an incoming Cookie into it's parts - * - * @param string $cookie_str content of cookie - * @return array with data of that cookie - * @access private - */ - /* - * TODO: allow a Set-Cookie string to be parsed into multiple cookies - */ - function parseCookie($cookie_str) { - $cookie_str = str_replace('; ', ';', $cookie_str) . ';'; - $data = preg_split('/;/', $cookie_str); - $value_str = $data[0]; - - $cookie_param = 'domain='; - $start = strpos($cookie_str, $cookie_param); - if ($start > 0) { - $domain = substr($cookie_str, $start + strlen($cookie_param)); - $domain = substr($domain, 0, strpos($domain, ';')); - } else { - $domain = ''; - } - - $cookie_param = 'expires='; - $start = strpos($cookie_str, $cookie_param); - if ($start > 0) { - $expires = substr($cookie_str, $start + strlen($cookie_param)); - $expires = substr($expires, 0, strpos($expires, ';')); - } else { - $expires = ''; - } - - $cookie_param = 'path='; - $start = strpos($cookie_str, $cookie_param); - if ( $start > 0 ) { - $path = substr($cookie_str, $start + strlen($cookie_param)); - $path = substr($path, 0, strpos($path, ';')); - } else { - $path = '/'; - } - - $cookie_param = ';secure;'; - if (strpos($cookie_str, $cookie_param) !== FALSE) { - $secure = true; - } else { - $secure = false; - } - - $sep_pos = strpos($value_str, '='); - - if ($sep_pos) { - $name = substr($value_str, 0, $sep_pos); - $value = substr($value_str, $sep_pos + 1); - $cookie= array( 'name' => $name, - 'value' => $value, - 'domain' => $domain, - 'path' => $path, - 'expires' => $expires, - 'secure' => $secure - ); - return $cookie; - } - return false; - } - - /** - * sort out cookies for the current request - * - * @param array $cookies array with all cookies - * @param boolean $secure is the send-content secure or not? - * @return string for Cookie-HTTP-Header - * @access private - */ - function getCookiesForRequest($cookies, $secure=false) { - $cookie_str = ''; - if ((! is_null($cookies)) && (is_array($cookies))) { - foreach ($cookies as $cookie) { - if (! is_array($cookie)) { - continue; - } - $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']); - if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) { - if (strtotime($cookie['expires']) <= time()) { - $this->debug('cookie has expired'); - continue; - } - } - if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) { - $domain = preg_quote($cookie['domain']); - if (! preg_match("'.*$domain$'i", $this->host)) { - $this->debug('cookie has different domain'); - continue; - } - } - if ((isset($cookie['path'])) && (! empty($cookie['path']))) { - $path = preg_quote($cookie['path']); - if (! preg_match("'^$path.*'i", $this->path)) { - $this->debug('cookie is for a different path'); - continue; - } - } - if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) { - $this->debug('cookie is secure, transport is not'); - continue; - } - $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; '; - $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']); - } - } - return $cookie_str; - } -} - -?> -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_server extends nusoap_base { - /** - * HTTP headers of request - * @var array - * @access private - */ - var $headers = array(); - /** - * HTTP request - * @var string - * @access private - */ - var $request = ''; - /** - * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text) - * @var string - * @access public - */ - var $requestHeaders = ''; - /** - * SOAP Headers from request (parsed) - * @var mixed - * @access public - */ - var $requestHeader = NULL; - /** - * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text) - * @var string - * @access public - */ - var $document = ''; - /** - * SOAP payload for request (text) - * @var string - * @access public - */ - var $requestSOAP = ''; - /** - * requested method namespace URI - * @var string - * @access private - */ - var $methodURI = ''; - /** - * name of method requested - * @var string - * @access private - */ - var $methodname = ''; - /** - * method parameters from request - * @var array - * @access private - */ - var $methodparams = array(); - /** - * SOAP Action from request - * @var string - * @access private - */ - var $SOAPAction = ''; - /** - * character set encoding of incoming (request) messages - * @var string - * @access public - */ - var $xml_encoding = ''; - /** - * toggles whether the parser decodes element content w/ utf8_decode() - * @var boolean - * @access public - */ - var $decode_utf8 = true; - - /** - * HTTP headers of response - * @var array - * @access public - */ - var $outgoing_headers = array(); - /** - * HTTP response - * @var string - * @access private - */ - var $response = ''; - /** - * SOAP headers for response (text or array of soapval or associative array) - * @var mixed - * @access public - */ - var $responseHeaders = ''; - /** - * SOAP payload for response (text) - * @var string - * @access private - */ - var $responseSOAP = ''; - /** - * method return value to place in response - * @var mixed - * @access private - */ - var $methodreturn = false; - /** - * whether $methodreturn is a string of literal XML - * @var boolean - * @access public - */ - var $methodreturnisliteralxml = false; - /** - * SOAP fault for response (or false) - * @var mixed - * @access private - */ - var $fault = false; - /** - * text indication of result (for debugging) - * @var string - * @access private - */ - var $result = 'successful'; - - /** - * assoc array of operations => opData; operations are added by the register() - * method or by parsing an external WSDL definition - * @var array - * @access private - */ - var $operations = array(); - /** - * wsdl instance (if one) - * @var mixed - * @access private - */ - var $wsdl = false; - /** - * URL for WSDL (if one) - * @var mixed - * @access private - */ - var $externalWSDLURL = false; - /** - * whether to append debug to response as XML comment - * @var boolean - * @access public - */ - var $debug_flag = false; - - - /** - * constructor - * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to. - * - * @param mixed $wsdl file path or URL (string), or wsdl instance (object) - * @access public - */ - function nusoap_server($wsdl=false){ - parent::nusoap_base(); - // turn on debugging? - global $debug; - global $HTTP_SERVER_VARS; - - if (isset($_SERVER)) { - $this->debug("_SERVER is defined:"); - $this->appendDebug($this->varDump($_SERVER)); - } elseif (isset($HTTP_SERVER_VARS)) { - $this->debug("HTTP_SERVER_VARS is defined:"); - $this->appendDebug($this->varDump($HTTP_SERVER_VARS)); - } else { - $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined."); - } - - if (isset($debug)) { - $this->debug("In nusoap_server, set debug_flag=$debug based on global flag"); - $this->debug_flag = $debug; - } elseif (isset($_SERVER['QUERY_STRING'])) { - $qs = explode('&', $_SERVER['QUERY_STRING']); - foreach ($qs as $v) { - if (substr($v, 0, 6) == 'debug=') { - $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1"); - $this->debug_flag = substr($v, 6); - } - } - } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) { - $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']); - foreach ($qs as $v) { - if (substr($v, 0, 6) == 'debug=') { - $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2"); - $this->debug_flag = substr($v, 6); - } - } - } - - // wsdl - if($wsdl){ - $this->debug("In nusoap_server, WSDL is specified"); - if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) { - $this->wsdl = $wsdl; - $this->externalWSDLURL = $this->wsdl->wsdl; - $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL); - } else { - $this->debug('Create wsdl from ' . $wsdl); - $this->wsdl = new wsdl($wsdl); - $this->externalWSDLURL = $wsdl; - } - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - if($err = $this->wsdl->getError()){ - die('WSDL ERROR: '.$err); - } - } - } - - /** - * processes request and returns response - * - * @param string $data usually is the value of $HTTP_RAW_POST_DATA - * @access public - */ - function service($data){ - global $HTTP_SERVER_VARS; - - if (isset($_SERVER['REQUEST_METHOD'])) { - $rm = $_SERVER['REQUEST_METHOD']; - } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) { - $rm = $HTTP_SERVER_VARS['REQUEST_METHOD']; - } else { - $rm = ''; - } - - if (isset($_SERVER['QUERY_STRING'])) { - $qs = $_SERVER['QUERY_STRING']; - } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) { - $qs = $HTTP_SERVER_VARS['QUERY_STRING']; - } else { - $qs = ''; - } - $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data)); - - if ($rm == 'POST') { - $this->debug("In service, invoke the request"); - $this->parse_request($data); - if (! $this->fault) { - $this->invoke_method(); - } - if (! $this->fault) { - $this->serialize_return(); - } - $this->send_response(); - } elseif (preg_match('/wsdl/', $qs) ){ - $this->debug("In service, this is a request for WSDL"); - if ($this->externalWSDLURL){ - if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL - $this->debug("In service, re-direct for WSDL"); - header('Location: '.$this->externalWSDLURL); - } else { // assume file - $this->debug("In service, use file passthru for WSDL"); - header("Content-Type: text/xml\r\n"); - $pos = strpos($this->externalWSDLURL, "file://"); - if ($pos === false) { - $filename = $this->externalWSDLURL; - } else { - $filename = substr($this->externalWSDLURL, $pos + 7); - } - $fp = fopen($this->externalWSDLURL, 'r'); - fpassthru($fp); - } - } elseif ($this->wsdl) { - $this->debug("In service, serialize WSDL"); - header("Content-Type: text/xml; charset=ISO-8859-1\r\n"); - print $this->wsdl->serialize($this->debug_flag); - if ($this->debug_flag) { - $this->debug('wsdl:'); - $this->appendDebug($this->varDump($this->wsdl)); - print $this->getDebugAsXMLComment(); - } - } else { - $this->debug("In service, there is no WSDL"); - header("Content-Type: text/html; charset=ISO-8859-1\r\n"); - print "This service does not provide WSDL"; - } - } elseif ($this->wsdl) { - $this->debug("In service, return Web description"); - print $this->wsdl->webDescription(); - } else { - $this->debug("In service, no Web description"); - header("Content-Type: text/html; charset=ISO-8859-1\r\n"); - print "This service does not provide a Web description"; - } - } - - /** - * parses HTTP request headers. - * - * The following fields are set by this function (when successful) - * - * headers - * request - * xml_encoding - * SOAPAction - * - * @access private - */ - function parse_http_headers() { - global $HTTP_SERVER_VARS; - - $this->request = ''; - $this->SOAPAction = ''; - if(function_exists('getallheaders')){ - $this->debug("In parse_http_headers, use getallheaders"); - $headers = getallheaders(); - foreach($headers as $k=>$v){ - $k = strtolower($k); - $this->headers[$k] = $v; - $this->request .= "$k: $v\r\n"; - $this->debug("$k: $v"); - } - // get SOAPAction header - if(isset($this->headers['soapaction'])){ - $this->SOAPAction = str_replace('"','',$this->headers['soapaction']); - } - // get the character encoding of the incoming request - if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){ - $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1)); - if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){ - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - } elseif(isset($_SERVER) && is_array($_SERVER)){ - $this->debug("In parse_http_headers, use _SERVER"); - foreach ($_SERVER as $k => $v) { - if (substr($k, 0, 5) == 'HTTP_') { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); - } else { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); - } - if ($k == 'soapaction') { - // get SOAPAction header - $k = 'SOAPAction'; - $v = str_replace('"', '', $v); - $v = str_replace('\\', '', $v); - $this->SOAPAction = $v; - } else if ($k == 'content-type') { - // get the character encoding of the incoming request - if (strpos($v, '=')) { - $enc = substr(strstr($v, '='), 1); - $enc = str_replace('"', '', $enc); - $enc = str_replace('\\', '', $enc); - if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) { - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - } - $this->headers[$k] = $v; - $this->request .= "$k: $v\r\n"; - $this->debug("$k: $v"); - } - } elseif (is_array($HTTP_SERVER_VARS)) { - $this->debug("In parse_http_headers, use HTTP_SERVER_VARS"); - foreach ($HTTP_SERVER_VARS as $k => $v) { - if (substr($k, 0, 5) == 'HTTP_') { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5)); - } else { - $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k); - } - if ($k == 'soapaction') { - // get SOAPAction header - $k = 'SOAPAction'; - $v = str_replace('"', '', $v); - $v = str_replace('\\', '', $v); - $this->SOAPAction = $v; - } else if ($k == 'content-type') { - // get the character encoding of the incoming request - if (strpos($v, '=')) { - $enc = substr(strstr($v, '='), 1); - $enc = str_replace('"', '', $enc); - $enc = str_replace('\\', '', $enc); - if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) { - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - } - $this->headers[$k] = $v; - $this->request .= "$k: $v\r\n"; - $this->debug("$k: $v"); - } - } else { - $this->debug("In parse_http_headers, HTTP headers not accessible"); - $this->setError("HTTP headers not accessible"); - } - } - - /** - * parses a request - * - * The following fields are set by this function (when successful) - * - * headers - * request - * xml_encoding - * SOAPAction - * request - * requestSOAP - * methodURI - * methodname - * methodparams - * requestHeaders - * document - * - * This sets the fault field on error - * - * @param string $data XML string - * @access private - */ - function parse_request($data='') { - $this->debug('entering parse_request()'); - $this->parse_http_headers(); - $this->debug('got character encoding: '.$this->xml_encoding); - // uncompress if necessary - if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') { - $this->debug('got content encoding: ' . $this->headers['content-encoding']); - if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') { - // if decoding works, use it. else assume data wasn't gzencoded - if (function_exists('gzuncompress')) { - if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) { - $data = $degzdata; - } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) { - $data = $degzdata; - } else { - $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data'); - return; - } - } else { - $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data'); - return; - } - } - } - $this->request .= "\r\n".$data; - $data = $this->parseRequest($this->headers, $data); - $this->requestSOAP = $data; - $this->debug('leaving parse_request'); - } - - /** - * invokes a PHP function for the requested SOAP method - * - * The following fields are set by this function (when successful) - * - * methodreturn - * - * Note that the PHP function that is called may also set the following - * fields to affect the response sent to the client - * - * responseHeaders - * outgoing_headers - * - * This sets the fault field on error - * - * @access private - */ - function invoke_method() { - $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction); - - // - // if you are debugging in this area of the code, your service uses a class to implement methods, - // you use SOAP RPC, and the client is .NET, please be aware of the following... - // when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the - // method name. that is fine for naming the .NET methods. it is not fine for properly constructing - // the XML request and reading the XML response. you need to add the RequestElementName and - // ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe - // generates for the method. these parameters are used to specify the correct XML element names - // for .NET to use, i.e. the names with the '.' in them. - // - $orig_methodname = $this->methodname; - if ($this->wsdl) { - if ($this->opData = $this->wsdl->getOperationData($this->methodname)) { - $this->debug('in invoke_method, found WSDL operation=' . $this->methodname); - $this->appendDebug('opData=' . $this->varDump($this->opData)); - } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) { - // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element - $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']); - $this->appendDebug('opData=' . $this->varDump($this->opData)); - $this->methodname = $this->opData['name']; - } else { - $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname); - $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service"); - return; - } - } else { - $this->debug('in invoke_method, no WSDL to validate method'); - } - - // if a . is present in $this->methodname, we see if there is a class in scope, - // which could be referred to. We will also distinguish between two deliminators, - // to allow methods to be called a the class or an instance - if (strpos($this->methodname, '..') > 0) { - $delim = '..'; - } else if (strpos($this->methodname, '.') > 0) { - $delim = '.'; - } else { - $delim = ''; - } - $this->debug("in invoke_method, delim=$delim"); - - $class = ''; - $method = ''; - if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) { - $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim)); - if (class_exists($try_class)) { - // get the class and method name - $class = $try_class; - $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim)); - $this->debug("in invoke_method, class=$class method=$method delim=$delim"); - } else { - $this->debug("in invoke_method, class=$try_class not found"); - } - } else { - $try_class = ''; - $this->debug("in invoke_method, no class to try"); - } - - // does method exist? - if ($class == '') { - if (!function_exists($this->methodname)) { - $this->debug("in invoke_method, function '$this->methodname' not found!"); - $this->result = 'fault: method not found'; - $this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')"); - return; - } - } else { - $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method; - if (!in_array($method_to_compare, get_class_methods($class))) { - $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!"); - $this->result = 'fault: method not found'; - $this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')"); - return; - } - } - - // evaluate message, getting back parameters - // verify that request parameters match the method's signature - if(! $this->verify_method($this->methodname,$this->methodparams)){ - // debug - $this->debug('ERROR: request not verified against method signature'); - $this->result = 'fault: request failed validation against method signature'; - // return fault - $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service."); - return; - } - - // if there are parameters to pass - $this->debug('in invoke_method, params:'); - $this->appendDebug($this->varDump($this->methodparams)); - $this->debug("in invoke_method, calling '$this->methodname'"); - if (!function_exists('call_user_func_array')) { - if ($class == '') { - $this->debug('in invoke_method, calling function using eval()'); - $funcCall = "\$this->methodreturn = $this->methodname("; - } else { - if ($delim == '..') { - $this->debug('in invoke_method, calling class method using eval()'); - $funcCall = "\$this->methodreturn = ".$class."::".$method."("; - } else { - $this->debug('in invoke_method, calling instance method using eval()'); - // generate unique instance name - $instname = "\$inst_".time(); - $funcCall = $instname." = new ".$class."(); "; - $funcCall .= "\$this->methodreturn = ".$instname."->".$method."("; - } - } - if ($this->methodparams) { - foreach ($this->methodparams as $param) { - if (is_array($param) || is_object($param)) { - $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available'); - return; - } - $funcCall .= "\"$param\","; - } - $funcCall = substr($funcCall, 0, -1); - } - $funcCall .= ');'; - $this->debug('in invoke_method, function call: '.$funcCall); - @eval($funcCall); - } else { - if ($class == '') { - $this->debug('in invoke_method, calling function using call_user_func_array()'); - $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array() - } elseif ($delim == '..') { - $this->debug('in invoke_method, calling class method using call_user_func_array()'); - $call_arg = array ($class, $method); - } else { - $this->debug('in invoke_method, calling instance method using call_user_func_array()'); - $instance = new $class (); - $call_arg = array(&$instance, $method); - } - if (is_array($this->methodparams)) { - $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams)); - } else { - $this->methodreturn = call_user_func_array($call_arg, array()); - } - } - $this->debug('in invoke_method, methodreturn:'); - $this->appendDebug($this->varDump($this->methodreturn)); - $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn)); - } - - /** - * serializes the return value from a PHP function into a full SOAP Envelope - * - * The following fields are set by this function (when successful) - * - * responseSOAP - * - * This sets the fault field on error - * - * @access private - */ - function serialize_return() { - $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI); - // if fault - if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) { - $this->debug('got a fault object from method'); - $this->fault = $this->methodreturn; - return; - } elseif ($this->methodreturnisliteralxml) { - $return_val = $this->methodreturn; - // returned value(s) - } else { - $this->debug('got a(n) '.gettype($this->methodreturn).' from method'); - $this->debug('serializing return value'); - if($this->wsdl){ - if (sizeof($this->opData['output']['parts']) > 1) { - $this->debug('more than one output part, so use the method return unchanged'); - $opParams = $this->methodreturn; - } elseif (sizeof($this->opData['output']['parts']) == 1) { - $this->debug('exactly one output part, so wrap the method return in a simple array'); - // TODO: verify that it is not already wrapped! - //foreach ($this->opData['output']['parts'] as $name => $type) { - // $this->debug('wrap in element named ' . $name); - //} - $opParams = array($this->methodreturn); - } - $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams); - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - if($errstr = $this->wsdl->getError()){ - $this->debug('got wsdl error: '.$errstr); - $this->fault('SOAP-ENV:Server', 'unable to serialize result'); - return; - } - } else { - if (isset($this->methodreturn)) { - $return_val = $this->serialize_val($this->methodreturn, 'return'); - } else { - $return_val = ''; - $this->debug('in absence of WSDL, assume void return for backward compatibility'); - } - } - } - $this->debug('return value:'); - $this->appendDebug($this->varDump($return_val)); - - $this->debug('serializing response'); - if ($this->wsdl) { - $this->debug('have WSDL for serialization: style is ' . $this->opData['style']); - if ($this->opData['style'] == 'rpc') { - $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']); - if ($this->opData['output']['use'] == 'literal') { - // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace - if ($this->methodURI) { - $payload = 'methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'methodname."Response>"; - } else { - $payload = '<'.$this->methodname.'Response>'.$return_val.'methodname.'Response>'; - } - } else { - if ($this->methodURI) { - $payload = 'methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'methodname."Response>"; - } else { - $payload = '<'.$this->methodname.'Response>'.$return_val.'methodname.'Response>'; - } - } - } else { - $this->debug('style is not rpc for serialization: assume document'); - $payload = $return_val; - } - } else { - $this->debug('do not have WSDL for serialization: assume rpc/encoded'); - $payload = 'methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'methodname."Response>"; - } - $this->result = 'successful'; - if($this->wsdl){ - //if($this->debug_flag){ - $this->appendDebug($this->wsdl->getDebug()); - // } - if (isset($this->opData['output']['encodingStyle'])) { - $encodingStyle = $this->opData['output']['encodingStyle']; - } else { - $encodingStyle = ''; - } - // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces. - $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle); - } else { - $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders); - } - $this->debug("Leaving serialize_return"); - } - - /** - * sends an HTTP response - * - * The following fields are set by this function (when successful) - * - * outgoing_headers - * response - * - * @access private - */ - function send_response() { - $this->debug('Enter send_response'); - if ($this->fault) { - $payload = $this->fault->serialize(); - $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error"; - $this->outgoing_headers[] = "Status: 500 Internal Server Error"; - } else { - $payload = $this->responseSOAP; - // Some combinations of PHP+Web server allow the Status - // to come through as a header. Since OK is the default - // just do nothing. - // $this->outgoing_headers[] = "HTTP/1.0 200 OK"; - // $this->outgoing_headers[] = "Status: 200 OK"; - } - // add debug data if in debug mode - if(isset($this->debug_flag) && $this->debug_flag){ - $payload .= $this->getDebugAsXMLComment(); - } - $this->outgoing_headers[] = "Server: $this->title Server v$this->version"; - preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev); - $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")"; - // Let the Web server decide about this - //$this->outgoing_headers[] = "Connection: Close\r\n"; - $payload = $this->getHTTPBody($payload); - $type = $this->getHTTPContentType(); - $charset = $this->getHTTPContentTypeCharset(); - $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : ''); - //begin code to compress payload - by John - // NOTE: there is no way to know whether the Web server will also compress - // this data. - if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) { - if (strstr($this->headers['accept-encoding'], 'gzip')) { - if (function_exists('gzencode')) { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ""; - } - $this->outgoing_headers[] = "Content-Encoding: gzip"; - $payload = gzencode($payload); - } else { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ""; - } - } - } elseif (strstr($this->headers['accept-encoding'], 'deflate')) { - // Note: MSIE requires gzdeflate output (no Zlib header and checksum), - // instead of gzcompress output, - // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5) - if (function_exists('gzdeflate')) { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ""; - } - $this->outgoing_headers[] = "Content-Encoding: deflate"; - $payload = gzdeflate($payload); - } else { - if (isset($this->debug_flag) && $this->debug_flag) { - $payload .= ""; - } - } - } - } - //end code - $this->outgoing_headers[] = "Content-Length: ".strlen($payload); - reset($this->outgoing_headers); - foreach($this->outgoing_headers as $hdr){ - header($hdr, false); - } - print $payload; - $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload; - } - - /** - * takes the value that was created by parsing the request - * and compares to the method's signature, if available. - * - * @param string $operation The operation to be invoked - * @param array $request The array of parameter values - * @return boolean Whether the operation was found - * @access private - */ - function verify_method($operation,$request){ - if(isset($this->wsdl) && is_object($this->wsdl)){ - if($this->wsdl->getOperationData($operation)){ - return true; - } - } elseif(isset($this->operations[$operation])){ - return true; - } - return false; - } - - /** - * processes SOAP message received from client - * - * @param array $headers The HTTP headers - * @param string $data unprocessed request data from client - * @return mixed value of the message, decoded into a PHP type - * @access private - */ - function parseRequest($headers, $data) { - $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:'); - $this->appendDebug($this->varDump($headers)); - if (!isset($headers['content-type'])) { - $this->setError('Request not of type text/xml (no content-type header)'); - return false; - } - if (!strstr($headers['content-type'], 'text/xml')) { - $this->setError('Request not of type text/xml'); - return false; - } - if (strpos($headers['content-type'], '=')) { - $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1)); - $this->debug('Got response encoding: ' . $enc); - if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){ - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser'); - // parse response, get soap parser obj - $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8); - // parser debug - $this->debug("parser debug: \n".$parser->getDebug()); - // if fault occurred during message parsing - if($err = $parser->getError()){ - $this->result = 'fault: error in msg parsing: '.$err; - $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err); - // else successfully parsed request into soapval object - } else { - // get/set methodname - $this->methodURI = $parser->root_struct_namespace; - $this->methodname = $parser->root_struct_name; - $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI); - $this->debug('calling parser->get_soapbody()'); - $this->methodparams = $parser->get_soapbody(); - // get SOAP headers - $this->requestHeaders = $parser->getHeaders(); - // get SOAP Header - $this->requestHeader = $parser->get_soapheader(); - // add document for doclit support - $this->document = $parser->document; - } - } - - /** - * gets the HTTP body for the current response. - * - * @param string $soapmsg The SOAP payload - * @return string The HTTP body, which includes the SOAP payload - * @access private - */ - function getHTTPBody($soapmsg) { - return $soapmsg; - } - - /** - * gets the HTTP content type for the current response. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type for the current response. - * @access private - */ - function getHTTPContentType() { - return 'text/xml'; - } - - /** - * gets the HTTP content type charset for the current response. - * returns false for non-text content types. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type charset for the current response. - * @access private - */ - function getHTTPContentTypeCharset() { - return $this->soap_defencoding; - } - - /** - * add a method to the dispatch map (this has been replaced by the register method) - * - * @param string $methodname - * @param string $in array of input values - * @param string $out array of output values - * @access public - * @deprecated - */ - function add_to_map($methodname,$in,$out){ - $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out); - } - - /** - * register a service function with the server - * - * @param string $name the name of the PHP function, class.method or class..method - * @param array $in assoc array of input values: key = param name, value = param type - * @param array $out assoc array of output values: key = param name, value = param type - * @param mixed $namespace the element namespace for the method or false - * @param mixed $soapaction the soapaction for the method or false - * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically - * @param mixed $use optional (encoded|literal) or false - * @param string $documentation optional Description to include in WSDL - * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) - * @access public - */ - function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){ - global $HTTP_SERVER_VARS; - - if($this->externalWSDLURL){ - die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.'); - } - if (! $name) { - die('You must specify a name when you register an operation'); - } - if (!is_array($in)) { - die('You must provide an array for operation inputs'); - } - if (!is_array($out)) { - die('You must provide an array for operation outputs'); - } - if(false == $namespace) { - } - if(false == $soapaction) { - if (isset($_SERVER)) { - $SERVER_NAME = $_SERVER['SERVER_NAME']; - $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']; - $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'); - } elseif (isset($HTTP_SERVER_VARS)) { - $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME']; - $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME']; - $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'; - } else { - $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); - } - if ($HTTPS == '1' || $HTTPS == 'on') { - $SCHEME = 'https'; - } else { - $SCHEME = 'http'; - } - $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name"; - } - if(false == $style) { - $style = "rpc"; - } - if(false == $use) { - $use = "encoded"; - } - if ($use == 'encoded' && $encodingStyle == '') { - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - } - - $this->operations[$name] = array( - 'name' => $name, - 'in' => $in, - 'out' => $out, - 'namespace' => $namespace, - 'soapaction' => $soapaction, - 'style' => $style); - if($this->wsdl){ - $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle); - } - return true; - } - - /** - * Specify a fault to be returned to the client. - * This also acts as a flag to the server that a fault has occured. - * - * @param string $faultcode - * @param string $faultstring - * @param string $faultactor - * @param string $faultdetail - * @access public - */ - function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){ - if ($faultdetail == '' && $this->debug_flag) { - $faultdetail = $this->getDebug(); - } - $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail); - $this->fault->soap_defencoding = $this->soap_defencoding; - } - - /** - * Sets up wsdl object. - * Acts as a flag to enable internal WSDL generation - * - * @param string $serviceName, name of the service - * @param mixed $namespace optional 'tns' service namespace or false - * @param mixed $endpoint optional URL of service endpoint or false - * @param string $style optional (rpc|document) WSDL style (also specified by operation) - * @param string $transport optional SOAP transport - * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false - */ - function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false) - { - global $HTTP_SERVER_VARS; - - if (isset($_SERVER)) { - $SERVER_NAME = $_SERVER['SERVER_NAME']; - $SERVER_PORT = $_SERVER['SERVER_PORT']; - $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']; - $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'); - } elseif (isset($HTTP_SERVER_VARS)) { - $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME']; - $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT']; - $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME']; - $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'; - } else { - $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); - } - // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI) - $colon = strpos($SERVER_NAME,":"); - if ($colon) { - $SERVER_NAME = substr($SERVER_NAME, 0, $colon); - } - if ($SERVER_PORT == 80) { - $SERVER_PORT = ''; - } else { - $SERVER_PORT = ':' . $SERVER_PORT; - } - if(false == $namespace) { - $namespace = "http://$SERVER_NAME/soap/$serviceName"; - } - - if(false == $endpoint) { - if ($HTTPS == '1' || $HTTPS == 'on') { - $SCHEME = 'https'; - } else { - $SCHEME = 'http'; - } - $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME"; - } - - if(false == $schemaTargetNamespace) { - $schemaTargetNamespace = $namespace; - } - - $this->wsdl = new wsdl; - $this->wsdl->serviceName = $serviceName; - $this->wsdl->endpoint = $endpoint; - $this->wsdl->namespaces['tns'] = $namespace; - $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/'; - $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/'; - if ($schemaTargetNamespace != $namespace) { - $this->wsdl->namespaces['types'] = $schemaTargetNamespace; - } - $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces); - if ($style == 'document') { - $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified'; - } - $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace; - $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true); - $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true); - $this->wsdl->bindings[$serviceName.'Binding'] = array( - 'name'=>$serviceName.'Binding', - 'style'=>$style, - 'transport'=>$transport, - 'portType'=>$serviceName.'PortType'); - $this->wsdl->ports[$serviceName.'Port'] = array( - 'binding'=>$serviceName.'Binding', - 'location'=>$endpoint, - 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/'); - } -} - -/** - * Backward compatibility - */ -class soap_server extends nusoap_server { -} - -?> -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class wsdl extends nusoap_base { - // URL or filename of the root of this WSDL - var $wsdl; - // define internal arrays of bindings, ports, operations, messages, etc. - var $schemas = array(); - var $currentSchema; - var $message = array(); - var $complexTypes = array(); - var $messages = array(); - var $currentMessage; - var $currentOperation; - var $portTypes = array(); - var $currentPortType; - var $bindings = array(); - var $currentBinding; - var $ports = array(); - var $currentPort; - var $opData = array(); - var $status = ''; - var $documentation = false; - var $endpoint = ''; - // array of wsdl docs to import - var $import = array(); - // parser vars - var $parser; - var $position = 0; - var $depth = 0; - var $depth_array = array(); - // for getting wsdl - var $proxyhost = ''; - var $proxyport = ''; - var $proxyusername = ''; - var $proxypassword = ''; - var $timeout = 0; - var $response_timeout = 30; - var $curl_options = array(); // User-specified cURL options - var $use_curl = false; // whether to always try to use cURL - // for HTTP authentication - var $username = ''; // Username for HTTP authentication - var $password = ''; // Password for HTTP authentication - var $authtype = ''; // Type of HTTP authentication - var $certRequest = array(); // Certificate for HTTP SSL authentication - - /** - * constructor - * - * @param string $wsdl WSDL document URL - * @param string $proxyhost - * @param string $proxyport - * @param string $proxyusername - * @param string $proxypassword - * @param integer $timeout set the connection timeout - * @param integer $response_timeout set the response timeout - * @param array $curl_options user-specified cURL options - * @param boolean $use_curl try to use cURL - * @access public - */ - function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){ - parent::nusoap_base(); - $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout"); - $this->proxyhost = $proxyhost; - $this->proxyport = $proxyport; - $this->proxyusername = $proxyusername; - $this->proxypassword = $proxypassword; - $this->timeout = $timeout; - $this->response_timeout = $response_timeout; - if (is_array($curl_options)) - $this->curl_options = $curl_options; - $this->use_curl = $use_curl; - $this->fetchWSDL($wsdl); - } - - /** - * fetches the WSDL document and parses it - * - * @access public - */ - function fetchWSDL($wsdl) { - $this->debug("parse and process WSDL path=$wsdl"); - $this->wsdl = $wsdl; - // parse wsdl file - if ($this->wsdl != "") { - $this->parseWSDL($this->wsdl); - } - // imports - // TODO: handle imports more properly, grabbing them in-line and nesting them - $imported_urls = array(); - $imported = 1; - while ($imported > 0) { - $imported = 0; - // Schema imports - foreach ($this->schemas as $ns => $list) { - foreach ($list as $ilist => $xs) { - $wsdlparts = parse_url($this->wsdl); // this is bogusly simple! - foreach ($xs->imports as $ns2 => $list2) { - for ($ii = 0; $ii < count($list2); $ii++) { - if (! $list2[$ii]['loaded']) { - $this->schemas[$ns][$ilist]->imports[$ns2][$ii]['loaded'] = true; - $url = $list2[$ii]['location']; - if ($url != '') { - $urlparts = parse_url($url); - if (!isset($urlparts['host'])) { - $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') . - substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path']; - } - if (! in_array($url, $imported_urls)) { - $this->parseWSDL($url); - $imported++; - $imported_urls[] = $url; - } - } else { - $this->debug("Unexpected scenario: empty URL for unloaded import"); - } - } - } - } - } - } - // WSDL imports - $wsdlparts = parse_url($this->wsdl); // this is bogusly simple! - foreach ($this->import as $ns => $list) { - for ($ii = 0; $ii < count($list); $ii++) { - if (! $list[$ii]['loaded']) { - $this->import[$ns][$ii]['loaded'] = true; - $url = $list[$ii]['location']; - if ($url != '') { - $urlparts = parse_url($url); - if (!isset($urlparts['host'])) { - $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') . - substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path']; - } - if (! in_array($url, $imported_urls)) { - $this->parseWSDL($url); - $imported++; - $imported_urls[] = $url; - } - } else { - $this->debug("Unexpected scenario: empty URL for unloaded import"); - } - } - } - } - } - // add new data to operation data - foreach($this->bindings as $binding => $bindingData) { - if (isset($bindingData['operations']) && is_array($bindingData['operations'])) { - foreach($bindingData['operations'] as $operation => $data) { - $this->debug('post-parse data gathering for ' . $operation); - $this->bindings[$binding]['operations'][$operation]['input'] = - isset($this->bindings[$binding]['operations'][$operation]['input']) ? - array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) : - $this->portTypes[ $bindingData['portType'] ][$operation]['input']; - $this->bindings[$binding]['operations'][$operation]['output'] = - isset($this->bindings[$binding]['operations'][$operation]['output']) ? - array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) : - $this->portTypes[ $bindingData['portType'] ][$operation]['output']; - if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){ - $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ]; - } - if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){ - $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ]; - } - // Set operation style if necessary, but do not override one already provided - if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) { - $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style']; - } - $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : ''; - $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : ''; - $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : ''; - } - } - } - } - - /** - * parses the wsdl document - * - * @param string $wsdl path or URL - * @access private - */ - function parseWSDL($wsdl = '') { - $this->debug("parse WSDL at path=$wsdl"); - - if ($wsdl == '') { - $this->debug('no wsdl passed to parseWSDL()!!'); - $this->setError('no wsdl passed to parseWSDL()!!'); - return false; - } - - // parse $wsdl for url format - $wsdl_props = parse_url($wsdl); - - if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) { - $this->debug('getting WSDL http(s) URL ' . $wsdl); - // get wsdl - $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl); - $tr->request_method = 'GET'; - $tr->useSOAPAction = false; - if($this->proxyhost && $this->proxyport){ - $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword); - } - if ($this->authtype != '') { - $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest); - } - $tr->setEncoding('gzip, deflate'); - $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout); - //$this->debug("WSDL request\n" . $tr->outgoing_payload); - //$this->debug("WSDL response\n" . $tr->incoming_payload); - $this->appendDebug($tr->getDebug()); - // catch errors - if($err = $tr->getError() ){ - $errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err; - $this->debug($errstr); - $this->setError($errstr); - unset($tr); - return false; - } - unset($tr); - $this->debug("got WSDL URL"); - } else { - // $wsdl is not http(s), so treat it as a file URL or plain file path - if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) { - $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path']; - } else { - $path = $wsdl; - } - $this->debug('getting WSDL file ' . $path); - if ($fp = @fopen($path, 'r')) { - $wsdl_string = ''; - while ($data = fread($fp, 32768)) { - $wsdl_string .= $data; - } - fclose($fp); - } else { - $errstr = "Bad path to WSDL file $path"; - $this->debug($errstr); - $this->setError($errstr); - return false; - } - } - $this->debug('Parse WSDL'); - // end new code added - // Create an XML parser. - $this->parser = xml_parser_create(); - // Set the options for parsing the XML data. - // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); - xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); - // Set the object for the parser. - xml_set_object($this->parser, $this); - // Set the element handlers for the parser. - xml_set_element_handler($this->parser, 'start_element', 'end_element'); - xml_set_character_data_handler($this->parser, 'character_data'); - // Parse the XML file. - if (!xml_parse($this->parser, $wsdl_string, true)) { - // Display an error message. - $errstr = sprintf( - 'XML error parsing WSDL from %s on line %d: %s', - $wsdl, - xml_get_current_line_number($this->parser), - xml_error_string(xml_get_error_code($this->parser)) - ); - $this->debug($errstr); - $this->debug("XML payload:\n" . $wsdl_string); - $this->setError($errstr); - return false; - } - // free the parser - xml_parser_free($this->parser); - $this->debug('Parsing WSDL done'); - // catch wsdl parse errors - if($this->getError()){ - return false; - } - return true; - } - - /** - * start-element handler - * - * @param string $parser XML parser object - * @param string $name element name - * @param string $attrs associative array of attributes - * @access private - */ - function start_element($parser, $name, $attrs) - { - if ($this->status == 'schema') { - $this->currentSchema->schemaStartElement($parser, $name, $attrs); - $this->appendDebug($this->currentSchema->getDebug()); - $this->currentSchema->clearDebug(); - } elseif (preg_match('/schema$/', $name)) { - $this->debug('Parsing WSDL schema'); - // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")"); - $this->status = 'schema'; - $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces); - $this->currentSchema->schemaStartElement($parser, $name, $attrs); - $this->appendDebug($this->currentSchema->getDebug()); - $this->currentSchema->clearDebug(); - } else { - // position in the total number of elements, starting from 0 - $pos = $this->position++; - $depth = $this->depth++; - // set self as current value for this depth - $this->depth_array[$depth] = $pos; - $this->message[$pos] = array('cdata' => ''); - // process attributes - if (count($attrs) > 0) { - // register namespace declarations - foreach($attrs as $k => $v) { - if (preg_match('/^xmlns/',$k)) { - if ($ns_prefix = substr(strrchr($k, ':'), 1)) { - $this->namespaces[$ns_prefix] = $v; - } else { - $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v; - } - if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') { - $this->XMLSchemaVersion = $v; - $this->namespaces['xsi'] = $v . '-instance'; - } - } - } - // expand each attribute prefix to its namespace - foreach($attrs as $k => $v) { - $k = strpos($k, ':') ? $this->expandQname($k) : $k; - if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') { - $v = strpos($v, ':') ? $this->expandQname($v) : $v; - } - $eAttrs[$k] = $v; - } - $attrs = $eAttrs; - } else { - $attrs = array(); - } - // get element prefix, namespace and name - if (preg_match('/:/', $name)) { - // get ns prefix - $prefix = substr($name, 0, strpos($name, ':')); - // get ns - $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : ''; - // get unqualified name - $name = substr(strstr($name, ':'), 1); - } - // process attributes, expanding any prefixes to namespaces - // find status, register data - switch ($this->status) { - case 'message': - if ($name == 'part') { - if (isset($attrs['type'])) { - $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs)); - $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type']; - } - if (isset($attrs['element'])) { - $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs)); - $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^'; - } - } - break; - case 'portType': - switch ($name) { - case 'operation': - $this->currentPortOperation = $attrs['name']; - $this->debug("portType $this->currentPortType operation: $this->currentPortOperation"); - if (isset($attrs['parameterOrder'])) { - $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder']; - } - break; - case 'documentation': - $this->documentation = true; - break; - // merge input/output data - default: - $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : ''; - $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m; - break; - } - break; - case 'binding': - switch ($name) { - case 'binding': - // get ns prefix - if (isset($attrs['style'])) { - $this->bindings[$this->currentBinding]['prefix'] = $prefix; - } - $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs); - break; - case 'header': - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs; - break; - case 'operation': - if (isset($attrs['soapAction'])) { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction']; - } - if (isset($attrs['style'])) { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style']; - } - if (isset($attrs['name'])) { - $this->currentOperation = $attrs['name']; - $this->debug("current binding operation: $this->currentOperation"); - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name']; - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding; - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : ''; - } - break; - case 'input': - $this->opStatus = 'input'; - break; - case 'output': - $this->opStatus = 'output'; - break; - case 'body': - if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs); - } else { - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs; - } - break; - } - break; - case 'service': - switch ($name) { - case 'port': - $this->currentPort = $attrs['name']; - $this->debug('current port: ' . $this->currentPort); - $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']); - - break; - case 'address': - $this->ports[$this->currentPort]['location'] = $attrs['location']; - $this->ports[$this->currentPort]['bindingType'] = $namespace; - $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace; - $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location']; - break; - } - break; - } - // set status - switch ($name) { - case 'import': - if (isset($attrs['location'])) { - $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false); - $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')'); - } else { - $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true); - if (! $this->getPrefixFromNamespace($attrs['namespace'])) { - $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace']; - } - $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')'); - } - break; - //wait for schema - //case 'types': - // $this->status = 'schema'; - // break; - case 'message': - $this->status = 'message'; - $this->messages[$attrs['name']] = array(); - $this->currentMessage = $attrs['name']; - break; - case 'portType': - $this->status = 'portType'; - $this->portTypes[$attrs['name']] = array(); - $this->currentPortType = $attrs['name']; - break; - case "binding": - if (isset($attrs['name'])) { - // get binding name - if (strpos($attrs['name'], ':')) { - $this->currentBinding = $this->getLocalPart($attrs['name']); - } else { - $this->currentBinding = $attrs['name']; - } - $this->status = 'binding'; - $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']); - $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']); - } - break; - case 'service': - $this->serviceName = $attrs['name']; - $this->status = 'service'; - $this->debug('current service: ' . $this->serviceName); - break; - case 'definitions': - foreach ($attrs as $name => $value) { - $this->wsdl_info[$name] = $value; - } - break; - } - } - } - - /** - * end-element handler - * - * @param string $parser XML parser object - * @param string $name element name - * @access private - */ - function end_element($parser, $name){ - // unset schema status - if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) { - $this->status = ""; - $this->appendDebug($this->currentSchema->getDebug()); - $this->currentSchema->clearDebug(); - $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema; - $this->debug('Parsing WSDL schema done'); - } - if ($this->status == 'schema') { - $this->currentSchema->schemaEndElement($parser, $name); - } else { - // bring depth down a notch - $this->depth--; - } - // end documentation - if ($this->documentation) { - //TODO: track the node to which documentation should be assigned; it can be a part, message, etc. - //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation; - $this->documentation = false; - } - } - - /** - * element content handler - * - * @param string $parser XML parser object - * @param string $data element content - * @access private - */ - function character_data($parser, $data) - { - $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0; - if (isset($this->message[$pos]['cdata'])) { - $this->message[$pos]['cdata'] .= $data; - } - if ($this->documentation) { - $this->documentation .= $data; - } - } - - /** - * if authenticating, set user credentials here - * - * @param string $username - * @param string $password - * @param string $authtype (basic|digest|certificate|ntlm) - * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) - * @access public - */ - function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) { - $this->debug("setCredentials username=$username authtype=$authtype certRequest="); - $this->appendDebug($this->varDump($certRequest)); - $this->username = $username; - $this->password = $password; - $this->authtype = $authtype; - $this->certRequest = $certRequest; - } - - function getBindingData($binding) - { - if (is_array($this->bindings[$binding])) { - return $this->bindings[$binding]; - } - } - - /** - * returns an assoc array of operation names => operation data - * - * @param string $portName WSDL port name - * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported) - * @return array - * @access public - */ - function getOperations($portName = '', $bindingType = 'soap') { - $ops = array(); - if ($bindingType == 'soap') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; - } elseif ($bindingType == 'soap12') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - } else { - $this->debug("getOperations bindingType $bindingType may not be supported"); - } - $this->debug("getOperations for port '$portName' bindingType $bindingType"); - // loop thru ports - foreach($this->ports as $port => $portData) { - $this->debug("getOperations checking port $port bindingType " . $portData['bindingType']); - if ($portName == '' || $port == $portName) { - // binding type of port matches parameter - if ($portData['bindingType'] == $bindingType) { - $this->debug("getOperations found port $port bindingType $bindingType"); - //$this->debug("port data: " . $this->varDump($portData)); - //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ])); - // merge bindings - if (isset($this->bindings[ $portData['binding'] ]['operations'])) { - $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']); - } - } - } - } - if (count($ops) == 0) { - $this->debug("getOperations found no operations for port '$portName' bindingType $bindingType"); - } - return $ops; - } - - /** - * returns an associative array of data necessary for calling an operation - * - * @param string $operation name of operation - * @param string $bindingType type of binding eg: soap, soap12 - * @return array - * @access public - */ - function getOperationData($operation, $bindingType = 'soap') - { - if ($bindingType == 'soap') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; - } elseif ($bindingType == 'soap12') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - } - // loop thru ports - foreach($this->ports as $port => $portData) { - // binding type of port matches parameter - if ($portData['bindingType'] == $bindingType) { - // get binding - //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) { - foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) { - // note that we could/should also check the namespace here - if ($operation == $bOperation) { - $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation]; - return $opData; - } - } - } - } - } - - /** - * returns an associative array of data necessary for calling an operation - * - * @param string $soapAction soapAction for operation - * @param string $bindingType type of binding eg: soap, soap12 - * @return array - * @access public - */ - function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') { - if ($bindingType == 'soap') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; - } elseif ($bindingType == 'soap12') { - $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - } - // loop thru ports - foreach($this->ports as $port => $portData) { - // binding type of port matches parameter - if ($portData['bindingType'] == $bindingType) { - // loop through operations for the binding - foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) { - if ($opData['soapAction'] == $soapAction) { - return $opData; - } - } - } - } - } - - /** - * returns an array of information about a given type - * returns false if no type exists by the given name - * - * typeDef = array( - * 'elements' => array(), // refs to elements array - * 'restrictionBase' => '', - * 'phpType' => '', - * 'order' => '(sequence|all)', - * 'attrs' => array() // refs to attributes array - * ) - * - * @param string $type the type - * @param string $ns namespace (not prefix) of the type - * @return mixed - * @access public - * @see nusoap_xmlschema - */ - function getTypeDef($type, $ns) { - $this->debug("in getTypeDef: type=$type, ns=$ns"); - if ((! $ns) && isset($this->namespaces['tns'])) { - $ns = $this->namespaces['tns']; - $this->debug("in getTypeDef: type namespace forced to $ns"); - } - if (!isset($this->schemas[$ns])) { - foreach ($this->schemas as $ns0 => $schema0) { - if (strcasecmp($ns, $ns0) == 0) { - $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0"); - $ns = $ns0; - break; - } - } - } - if (isset($this->schemas[$ns])) { - $this->debug("in getTypeDef: have schema for namespace $ns"); - for ($i = 0; $i < count($this->schemas[$ns]); $i++) { - $xs = &$this->schemas[$ns][$i]; - $t = $xs->getTypeDef($type); - $this->appendDebug($xs->getDebug()); - $xs->clearDebug(); - if ($t) { - $this->debug("in getTypeDef: found type $type"); - if (!isset($t['phpType'])) { - // get info for type to tack onto the element - $uqType = substr($t['type'], strrpos($t['type'], ':') + 1); - $ns = substr($t['type'], 0, strrpos($t['type'], ':')); - $etype = $this->getTypeDef($uqType, $ns); - if ($etype) { - $this->debug("found type for [element] $type:"); - $this->debug($this->varDump($etype)); - if (isset($etype['phpType'])) { - $t['phpType'] = $etype['phpType']; - } - if (isset($etype['elements'])) { - $t['elements'] = $etype['elements']; - } - if (isset($etype['attrs'])) { - $t['attrs'] = $etype['attrs']; - } - } else { - $this->debug("did not find type for [element] $type"); - } - } - return $t; - } - } - $this->debug("in getTypeDef: did not find type $type"); - } else { - $this->debug("in getTypeDef: do not have schema for namespace $ns"); - } - return false; - } - - /** - * prints html description of services - * - * @access private - */ - function webDescription(){ - global $HTTP_SERVER_VARS; - - if (isset($_SERVER)) { - $PHP_SELF = $_SERVER['PHP_SELF']; - } elseif (isset($HTTP_SERVER_VARS)) { - $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF']; - } else { - $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); - } - - $b = ' - NuSOAP: '.$this->serviceName.' - - - - -
    -

    -
    '.$this->serviceName.'
    - -
    '; - return $b; - } - - /** - * serialize the parsed wsdl - * - * @param mixed $debug whether to put debug=1 in endpoint URL - * @return string serialization of WSDL - * @access public - */ - function serialize($debug = 0) - { - $xml = ''; - $xml .= "\nnamespaces as $k => $v) { - $xml .= " xmlns:$k=\"$v\""; - } - // 10.9.02 - add poulter fix for wsdl and tns declarations - if (isset($this->namespaces['wsdl'])) { - $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\""; - } - if (isset($this->namespaces['tns'])) { - $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\""; - } - $xml .= '>'; - // imports - if (sizeof($this->import) > 0) { - foreach($this->import as $ns => $list) { - foreach ($list as $ii) { - if ($ii['location'] != '') { - $xml .= ''; - } else { - $xml .= ''; - } - } - } - } - // types - if (count($this->schemas)>=1) { - $xml .= "\n\n"; - foreach ($this->schemas as $ns => $list) { - foreach ($list as $xs) { - $xml .= $xs->serializeSchema(); - } - } - $xml .= ''; - } - // messages - if (count($this->messages) >= 1) { - foreach($this->messages as $msgName => $msgParts) { - $xml .= "\n'; - if(is_array($msgParts)){ - foreach($msgParts as $partName => $partType) { - // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'
    '; - if (strpos($partType, ':')) { - $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType)); - } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) { - // print 'checking typemap: '.$this->XMLSchemaVersion.'
    '; - $typePrefix = 'xsd'; - } else { - foreach($this->typemap as $ns => $types) { - if (isset($types[$partType])) { - $typePrefix = $this->getPrefixFromNamespace($ns); - } - } - if (!isset($typePrefix)) { - die("$partType has no namespace!"); - } - } - $ns = $this->getNamespaceFromPrefix($typePrefix); - $localPart = $this->getLocalPart($partType); - $typeDef = $this->getTypeDef($localPart, $ns); - if ($typeDef['typeClass'] == 'element') { - $elementortype = 'element'; - if (substr($localPart, -1) == '^') { - $localPart = substr($localPart, 0, -1); - } - } else { - $elementortype = 'type'; - } - $xml .= "\n" . ' '; - } - } - $xml .= '
    '; - } - } - // bindings & porttypes - if (count($this->bindings) >= 1) { - $binding_xml = ''; - $portType_xml = ''; - foreach($this->bindings as $bindingName => $attrs) { - $binding_xml .= "\n'; - $binding_xml .= "\n" . ' '; - $portType_xml .= "\n'; - foreach($attrs['operations'] as $opName => $opParts) { - $binding_xml .= "\n" . ' '; - $binding_xml .= "\n" . ' '; - if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') { - $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"'; - } else { - $enc_style = ''; - } - $binding_xml .= "\n" . ' '; - if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') { - $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"'; - } else { - $enc_style = ''; - } - $binding_xml .= "\n" . ' '; - $binding_xml .= "\n" . ' '; - $portType_xml .= "\n" . ' ' . htmlspecialchars($opParts['documentation']) . ''; - } - $portType_xml .= "\n" . ' '; - $portType_xml .= "\n" . ' '; - $portType_xml .= "\n" . ' '; - } - $portType_xml .= "\n" . ''; - $binding_xml .= "\n" . ''; - } - $xml .= $portType_xml . $binding_xml; - } - // services - $xml .= "\nserviceName . '">'; - if (count($this->ports) >= 1) { - foreach($this->ports as $pName => $attrs) { - $xml .= "\n" . ' '; - $xml .= "\n" . ' '; - $xml .= "\n" . ' '; - } - } - $xml .= "\n" . ''; - return $xml . "\n"; - } - - /** - * determine whether a set of parameters are unwrapped - * when they are expect to be wrapped, Microsoft-style. - * - * @param string $type the type (element name) of the wrapper - * @param array $parameters the parameter values for the SOAP call - * @return boolean whether they parameters are unwrapped (and should be wrapped) - * @access private - */ - function parametersMatchWrapped($type, &$parameters) { - $this->debug("in parametersMatchWrapped type=$type, parameters="); - $this->appendDebug($this->varDump($parameters)); - - // split type into namespace:unqualified-type - if (strpos($type, ':')) { - $uqType = substr($type, strrpos($type, ':') + 1); - $ns = substr($type, 0, strrpos($type, ':')); - $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns"); - if ($this->getNamespaceFromPrefix($ns)) { - $ns = $this->getNamespaceFromPrefix($ns); - $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns"); - } - } else { - // TODO: should the type be compared to types in XSD, and the namespace - // set to XSD if the type matches? - $this->debug("in parametersMatchWrapped: No namespace for type $type"); - $ns = ''; - $uqType = $type; - } - - // get the type information - if (!$typeDef = $this->getTypeDef($uqType, $ns)) { - $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type."); - return false; - } - $this->debug("in parametersMatchWrapped: found typeDef="); - $this->appendDebug($this->varDump($typeDef)); - if (substr($uqType, -1) == '^') { - $uqType = substr($uqType, 0, -1); - } - $phpType = $typeDef['phpType']; - $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''); - $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType"); - - // we expect a complexType or element of complexType - if ($phpType != 'struct') { - $this->debug("in parametersMatchWrapped: not a struct"); - return false; - } - - // see whether the parameter names match the elements - if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { - $elements = 0; - $matches = 0; - foreach ($typeDef['elements'] as $name => $attrs) { - if (isset($parameters[$name])) { - $this->debug("in parametersMatchWrapped: have parameter named $name"); - $matches++; - } else { - $this->debug("in parametersMatchWrapped: do not have parameter named $name"); - } - $elements++; - } - - $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names"); - if ($matches == 0) { - return false; - } - return true; - } - - // since there are no elements for the type, if the user passed no - // parameters, the parameters match wrapped. - $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType"); - return count($parameters) == 0; - } - - /** - * serialize PHP values according to a WSDL message definition - * contrary to the method name, this is not limited to RPC - * - * TODO - * - multi-ref serialization - * - validate PHP values against type definitions, return errors if invalid - * - * @param string $operation operation name - * @param string $direction (input|output) - * @param mixed $parameters parameter value(s) - * @param string $bindingType (soap|soap12) - * @return mixed parameters serialized as XML or false on error (e.g. operation not found) - * @access public - */ - function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') { - $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType"); - $this->appendDebug('parameters=' . $this->varDump($parameters)); - - if ($direction != 'input' && $direction != 'output') { - $this->debug('The value of the \$direction argument needs to be either "input" or "output"'); - $this->setError('The value of the \$direction argument needs to be either "input" or "output"'); - return false; - } - if (!$opData = $this->getOperationData($operation, $bindingType)) { - $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType); - $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType); - return false; - } - $this->debug('in serializeRPCParameters: opData:'); - $this->appendDebug($this->varDump($opData)); - - // Get encoding style for output and set to current - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) { - $encodingStyle = $opData['output']['encodingStyle']; - $enc_style = $encodingStyle; - } - - // set input params - $xml = ''; - if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) { - $parts = &$opData[$direction]['parts']; - $part_count = sizeof($parts); - $style = $opData['style']; - $use = $opData[$direction]['use']; - $this->debug("have $part_count part(s) to serialize using $style/$use"); - if (is_array($parameters)) { - $parametersArrayType = $this->isArraySimpleOrStruct($parameters); - $parameter_count = count($parameters); - $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize"); - // check for Microsoft-style wrapped parameters - if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) { - $this->debug('check whether the caller has wrapped the parameters'); - if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) { - // TODO: consider checking here for double-wrapping, when - // service function wraps, then NuSOAP wraps again - $this->debug("change simple array to associative with 'parameters' element"); - $parameters['parameters'] = $parameters[0]; - unset($parameters[0]); - } - if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) { - $this->debug('check whether caller\'s parameters match the wrapped ones'); - if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) { - $this->debug('wrap the parameters for the caller'); - $parameters = array('parameters' => $parameters); - $parameter_count = 1; - } - } - } - foreach ($parts as $name => $type) { - $this->debug("serializing part $name of type $type"); - // Track encoding style - if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) { - $encodingStyle = $opData[$direction]['encodingStyle']; - $enc_style = $encodingStyle; - } else { - $enc_style = false; - } - // NOTE: add error handling here - // if serializeType returns false, then catch global error and fault - if ($parametersArrayType == 'arraySimple') { - $p = array_shift($parameters); - $this->debug('calling serializeType w/indexed param'); - $xml .= $this->serializeType($name, $type, $p, $use, $enc_style); - } elseif (isset($parameters[$name])) { - $this->debug('calling serializeType w/named param'); - $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style); - } else { - // TODO: only send nillable - $this->debug('calling serializeType w/null param'); - $xml .= $this->serializeType($name, $type, null, $use, $enc_style); - } - } - } else { - $this->debug('no parameters passed.'); - } - } - $this->debug("serializeRPCParameters returning: $xml"); - return $xml; - } - - /** - * serialize a PHP value according to a WSDL message definition - * - * TODO - * - multi-ref serialization - * - validate PHP values against type definitions, return errors if invalid - * - * @param string $operation operation name - * @param string $direction (input|output) - * @param mixed $parameters parameter value(s) - * @return mixed parameters serialized as XML or false on error (e.g. operation not found) - * @access public - * @deprecated - */ - function serializeParameters($operation, $direction, $parameters) - { - $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion"); - $this->appendDebug('parameters=' . $this->varDump($parameters)); - - if ($direction != 'input' && $direction != 'output') { - $this->debug('The value of the \$direction argument needs to be either "input" or "output"'); - $this->setError('The value of the \$direction argument needs to be either "input" or "output"'); - return false; - } - if (!$opData = $this->getOperationData($operation)) { - $this->debug('Unable to retrieve WSDL data for operation: ' . $operation); - $this->setError('Unable to retrieve WSDL data for operation: ' . $operation); - return false; - } - $this->debug('opData:'); - $this->appendDebug($this->varDump($opData)); - - // Get encoding style for output and set to current - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) { - $encodingStyle = $opData['output']['encodingStyle']; - $enc_style = $encodingStyle; - } - - // set input params - $xml = ''; - if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) { - - $use = $opData[$direction]['use']; - $this->debug("use=$use"); - $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)'); - if (is_array($parameters)) { - $parametersArrayType = $this->isArraySimpleOrStruct($parameters); - $this->debug('have ' . $parametersArrayType . ' parameters'); - foreach($opData[$direction]['parts'] as $name => $type) { - $this->debug('serializing part "'.$name.'" of type "'.$type.'"'); - // Track encoding style - if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) { - $encodingStyle = $opData[$direction]['encodingStyle']; - $enc_style = $encodingStyle; - } else { - $enc_style = false; - } - // NOTE: add error handling here - // if serializeType returns false, then catch global error and fault - if ($parametersArrayType == 'arraySimple') { - $p = array_shift($parameters); - $this->debug('calling serializeType w/indexed param'); - $xml .= $this->serializeType($name, $type, $p, $use, $enc_style); - } elseif (isset($parameters[$name])) { - $this->debug('calling serializeType w/named param'); - $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style); - } else { - // TODO: only send nillable - $this->debug('calling serializeType w/null param'); - $xml .= $this->serializeType($name, $type, null, $use, $enc_style); - } - } - } else { - $this->debug('no parameters passed.'); - } - } - $this->debug("serializeParameters returning: $xml"); - return $xml; - } - - /** - * serializes a PHP value according a given type definition - * - * @param string $name name of value (part or element) - * @param string $type XML schema type of value (type or element) - * @param mixed $value a native PHP value (parameter value) - * @param string $use use for part (encoded|literal) - * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style) - * @param boolean $unqualified a kludge for what should be XML namespace form handling - * @return string value serialized as an XML string - * @access private - */ - function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false) - { - $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified")); - $this->appendDebug("value=" . $this->varDump($value)); - if($use == 'encoded' && $encodingStyle) { - $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"'; - } - - // if a soapval has been supplied, let its type override the WSDL - if (is_object($value) && get_class($value) == 'soapval') { - if ($value->type_ns) { - $type = $value->type_ns . ':' . $value->type; - $forceType = true; - $this->debug("in serializeType: soapval overrides type to $type"); - } elseif ($value->type) { - $type = $value->type; - $forceType = true; - $this->debug("in serializeType: soapval overrides type to $type"); - } else { - $forceType = false; - $this->debug("in serializeType: soapval does not override type"); - } - $attrs = $value->attributes; - $value = $value->value; - $this->debug("in serializeType: soapval overrides value to $value"); - if ($attrs) { - if (!is_array($value)) { - $value['!'] = $value; - } - foreach ($attrs as $n => $v) { - $value['!' . $n] = $v; - } - $this->debug("in serializeType: soapval provides attributes"); - } - } else { - $forceType = false; - } - - $xml = ''; - if (strpos($type, ':')) { - $uqType = substr($type, strrpos($type, ':') + 1); - $ns = substr($type, 0, strrpos($type, ':')); - $this->debug("in serializeType: got a prefixed type: $uqType, $ns"); - if ($this->getNamespaceFromPrefix($ns)) { - $ns = $this->getNamespaceFromPrefix($ns); - $this->debug("in serializeType: expanded prefixed type: $uqType, $ns"); - } - - if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){ - $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type'); - if ($unqualified && $use == 'literal') { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - if (is_null($value)) { - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$name$elementNS/>"; - } else { - // TODO: depends on nillable, which should be checked before calling this method - $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - if ($uqType == 'Array') { - // JBoss/Axis does this sometimes - return $this->serialize_val($value, $name, false, false, false, false, $use); - } - if ($uqType == 'boolean') { - if ((is_string($value) && $value == 'false') || (! $value)) { - $value = 'false'; - } else { - $value = 'true'; - } - } - if ($uqType == 'string' && gettype($value) == 'string') { - $value = $this->expandEntities($value); - } - if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') { - $value = sprintf("%.0lf", $value); - } - // it's a scalar - // TODO: what about null/nil values? - // check type isn't a custom type extending xmlschema namespace - if (!$this->getTypeDef($uqType, $ns)) { - if ($use == 'literal') { - if ($forceType) { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value"; - } else { - $xml = "<$name$elementNS>$value"; - } - } else { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)'); - } else if ($ns == 'http://xml.apache.org/xml-soap') { - $this->debug('in serializeType: appears to be Apache SOAP type'); - if ($uqType == 'Map') { - $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); - if (! $tt_prefix) { - $this->debug('in serializeType: Add namespace for Apache SOAP type'); - $tt_prefix = 'ns' . rand(1000, 9999); - $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap'; - // force this to be added to usedNamespaces - $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); - } - $contents = ''; - foreach($value as $k => $v) { - $this->debug("serializing map element: key $k, value $v"); - $contents .= ''; - $contents .= $this->serialize_val($k,'key',false,false,false,false,$use); - $contents .= $this->serialize_val($v,'value',false,false,false,false,$use); - $contents .= ''; - } - if ($use == 'literal') { - if ($forceType) { - $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents"; - } else { - $xml = "<$name>$contents"; - } - } else { - $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - $this->debug('in serializeType: Apache SOAP type, but only support Map'); - } - } else { - // TODO: should the type be compared to types in XSD, and the namespace - // set to XSD if the type matches? - $this->debug("in serializeType: No namespace for type $type"); - $ns = ''; - $uqType = $type; - } - if(!$typeDef = $this->getTypeDef($uqType, $ns)){ - $this->setError("$type ($uqType) is not a supported type."); - $this->debug("in serializeType: $type ($uqType) is not a supported type."); - return false; - } else { - $this->debug("in serializeType: found typeDef"); - $this->appendDebug('typeDef=' . $this->varDump($typeDef)); - if (substr($uqType, -1) == '^') { - $uqType = substr($uqType, 0, -1); - } - } - if (!isset($typeDef['phpType'])) { - $this->setError("$type ($uqType) has no phpType."); - $this->debug("in serializeType: $type ($uqType) has no phpType."); - return false; - } - $phpType = $typeDef['phpType']; - $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') ); - // if php type == struct, map value to the element names - if ($phpType == 'struct') { - if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') { - $elementName = $uqType; - if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { - $elementNS = " xmlns=\"$ns\""; - } else { - $elementNS = " xmlns=\"\""; - } - } else { - $elementName = $name; - if ($unqualified) { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - } - if (is_null($value)) { - if ($use == 'literal') { - // TODO: depends on minOccurs and nillable - $xml = "<$elementName$elementNS/>"; - } else { - $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - if (is_object($value)) { - $value = get_object_vars($value); - } - if (is_array($value)) { - $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType); - if ($use == 'literal') { - if ($forceType) { - $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">"; - } else { - $xml = "<$elementName$elementNS$elementAttrs>"; - } - } else { - $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>"; - } - - if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') { - if (isset($value['!'])) { - $xml .= $value['!']; - $this->debug("in serializeType: serialized simpleContent for type $type"); - } else { - $this->debug("in serializeType: no simpleContent to serialize for type $type"); - } - } else { - // complexContent - $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle); - } - $xml .= ""; - } else { - $this->debug("in serializeType: phpType is struct, but value is not an array"); - $this->setError("phpType is struct, but value is not an array: see debug output for details"); - $xml = ''; - } - } elseif ($phpType == 'array') { - if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { - $elementNS = " xmlns=\"$ns\""; - } else { - if ($unqualified) { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - } - if (is_null($value)) { - if ($use == 'literal') { - // TODO: depends on minOccurs - $xml = "<$name$elementNS/>"; - } else { - $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . - $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . - ":Array\" " . - $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . - ':arrayType="' . - $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) . - ':' . - $this->getLocalPart($typeDef['arrayType'])."[0]\"/>"; - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - if (isset($typeDef['multidimensional'])) { - $nv = array(); - foreach($value as $v) { - $cols = ',' . sizeof($v); - $nv = array_merge($nv, $v); - } - $value = $nv; - } else { - $cols = ''; - } - if (is_array($value) && sizeof($value) >= 1) { - $rows = sizeof($value); - $contents = ''; - foreach($value as $k => $v) { - $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]"); - //if (strpos($typeDef['arrayType'], ':') ) { - if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) { - $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use); - } else { - $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use); - } - } - } else { - $rows = 0; - $contents = null; - } - // TODO: for now, an empty value will be serialized as a zero element - // array. Revisit this when coding the handling of null/nil values. - if ($use == 'literal') { - $xml = "<$name$elementNS>" - .$contents - .""; - } else { - $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '. - $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') - .':arrayType="' - .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) - .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">" - .$contents - .""; - } - } elseif ($phpType == 'scalar') { - if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { - $elementNS = " xmlns=\"$ns\""; - } else { - if ($unqualified) { - $elementNS = " xmlns=\"\""; - } else { - $elementNS = ''; - } - } - if ($use == 'literal') { - if ($forceType) { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value"; - } else { - $xml = "<$name$elementNS>$value"; - } - } else { - $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value"; - } - } - $this->debug("in serializeType: returning: $xml"); - return $xml; - } - - /** - * serializes the attributes for a complexType - * - * @param array $typeDef our internal representation of an XML schema type (or element) - * @param mixed $value a native PHP value (parameter value) - * @param string $ns the namespace of the type - * @param string $uqType the local part of the type - * @return string value serialized as an XML string - * @access private - */ - function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) { - $this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType"); - $xml = ''; - if (isset($typeDef['extensionBase'])) { - $nsx = $this->getPrefix($typeDef['extensionBase']); - $uqTypex = $this->getLocalPart($typeDef['extensionBase']); - if ($this->getNamespaceFromPrefix($nsx)) { - $nsx = $this->getNamespaceFromPrefix($nsx); - } - if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) { - $this->debug("serialize attributes for extension base $nsx:$uqTypex"); - $xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex); - } else { - $this->debug("extension base $nsx:$uqTypex is not a supported type"); - } - } - if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) { - $this->debug("serialize attributes for XML Schema type $ns:$uqType"); - if (is_array($value)) { - $xvalue = $value; - } elseif (is_object($value)) { - $xvalue = get_object_vars($value); - } else { - $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); - $xvalue = array(); - } - foreach ($typeDef['attrs'] as $aName => $attrs) { - if (isset($xvalue['!' . $aName])) { - $xname = '!' . $aName; - $this->debug("value provided for attribute $aName with key $xname"); - } elseif (isset($xvalue[$aName])) { - $xname = $aName; - $this->debug("value provided for attribute $aName with key $xname"); - } elseif (isset($attrs['default'])) { - $xname = '!' . $aName; - $xvalue[$xname] = $attrs['default']; - $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName); - } else { - $xname = ''; - $this->debug("no value provided for attribute $aName"); - } - if ($xname) { - $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\""; - } - } - } else { - $this->debug("no attributes to serialize for XML Schema type $ns:$uqType"); - } - return $xml; - } - - /** - * serializes the elements for a complexType - * - * @param array $typeDef our internal representation of an XML schema type (or element) - * @param mixed $value a native PHP value (parameter value) - * @param string $ns the namespace of the type - * @param string $uqType the local part of the type - * @param string $use use for part (encoded|literal) - * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style) - * @return string value serialized as an XML string - * @access private - */ - function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) { - $this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType"); - $xml = ''; - if (isset($typeDef['extensionBase'])) { - $nsx = $this->getPrefix($typeDef['extensionBase']); - $uqTypex = $this->getLocalPart($typeDef['extensionBase']); - if ($this->getNamespaceFromPrefix($nsx)) { - $nsx = $this->getNamespaceFromPrefix($nsx); - } - if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) { - $this->debug("serialize elements for extension base $nsx:$uqTypex"); - $xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle); - } else { - $this->debug("extension base $nsx:$uqTypex is not a supported type"); - } - } - if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { - $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType"); - if (is_array($value)) { - $xvalue = $value; - } elseif (is_object($value)) { - $xvalue = get_object_vars($value); - } else { - $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); - $xvalue = array(); - } - // toggle whether all elements are present - ideally should validate against schema - if (count($typeDef['elements']) != count($xvalue)){ - $optionals = true; - } - foreach ($typeDef['elements'] as $eName => $attrs) { - if (!isset($xvalue[$eName])) { - if (isset($attrs['default'])) { - $xvalue[$eName] = $attrs['default']; - $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName); - } - } - // if user took advantage of a minOccurs=0, then only serialize named parameters - if (isset($optionals) - && (!isset($xvalue[$eName])) - && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true') - ){ - if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') { - $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']); - } - // do nothing - $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing"); - } else { - // get value - if (isset($xvalue[$eName])) { - $v = $xvalue[$eName]; - } else { - $v = null; - } - if (isset($attrs['form'])) { - $unqualified = ($attrs['form'] == 'unqualified'); - } else { - $unqualified = false; - } - if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') { - $vv = $v; - foreach ($vv as $k => $v) { - if (isset($attrs['type']) || isset($attrs['ref'])) { - // serialize schema-defined type - $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); - } else { - // serialize generic type (can this ever really happen?) - $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use"); - $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use); - } - } - } else { - if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') { - // do nothing - } elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') { - // TODO: serialize a nil correctly, but for now serialize schema-defined type - $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); - } elseif (isset($attrs['type']) || isset($attrs['ref'])) { - // serialize schema-defined type - $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); - } else { - // serialize generic type (can this ever really happen?) - $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use"); - $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use); - } - } - } - } - } else { - $this->debug("no elements to serialize for XML Schema type $ns:$uqType"); - } - return $xml; - } - - /** - * adds an XML Schema complex type to the WSDL types - * - * @param string $name - * @param string $typeClass (complexType|simpleType|attribute) - * @param string $phpType currently supported are array and struct (php assoc array) - * @param string $compositor (all|sequence|choice) - * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param array $elements e.g. array ( name => array(name=>'',type=>'') ) - * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]')) - * @param string $arrayType as namespace:name (xsd:string) - * @see nusoap_xmlschema - * @access public - */ - function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') { - if (count($elements) > 0) { - $eElements = array(); - foreach($elements as $n => $e){ - // expand each element - $ee = array(); - foreach ($e as $k => $v) { - $k = strpos($k,':') ? $this->expandQname($k) : $k; - $v = strpos($v,':') ? $this->expandQname($v) : $v; - $ee[$k] = $v; - } - $eElements[$n] = $ee; - } - $elements = $eElements; - } - - if (count($attrs) > 0) { - foreach($attrs as $n => $a){ - // expand each attribute - foreach ($a as $k => $v) { - $k = strpos($k,':') ? $this->expandQname($k) : $k; - $v = strpos($v,':') ? $this->expandQname($v) : $v; - $aa[$k] = $v; - } - $eAttrs[$n] = $aa; - } - $attrs = $eAttrs; - } - - $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase; - $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType; - - $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; - $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType); - } - - /** - * adds an XML Schema simple type to the WSDL types - * - * @param string $name - * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) - * @param string $typeClass (should always be simpleType) - * @param string $phpType (should always be scalar) - * @param array $enumeration array of values - * @see nusoap_xmlschema - * @access public - */ - function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) { - $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase; - - $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; - $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration); - } - - /** - * adds an element to the WSDL types - * - * @param array $attrs attributes that must include name and type - * @see nusoap_xmlschema - * @access public - */ - function addElement($attrs) { - $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; - $this->schemas[$typens][0]->addElement($attrs); - } - - /** - * register an operation with the server - * - * @param string $name operation (method) name - * @param array $in assoc array of input values: key = param name, value = param type - * @param array $out assoc array of output values: key = param name, value = param type - * @param string $namespace optional The namespace for the operation - * @param string $soapaction optional The soapaction for the operation - * @param string $style (rpc|document) optional The style for the operation Note: when 'document' is specified, parameter and return wrappers are created for you automatically - * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now) - * @param string $documentation optional The description to include in the WSDL - * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) - * @access public - */ - function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){ - if ($use == 'encoded' && $encodingStyle == '') { - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - } - - if ($style == 'document') { - $elements = array(); - foreach ($in as $n => $t) { - $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified'); - } - $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements); - $this->addElement(array('name' => $name, 'type' => $name . 'RequestType')); - $in = array('parameters' => 'tns:' . $name . '^'); - - $elements = array(); - foreach ($out as $n => $t) { - $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified'); - } - $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements); - $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified')); - $out = array('parameters' => 'tns:' . $name . 'Response' . '^'); - } - - // get binding - $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] = - array( - 'name' => $name, - 'binding' => $this->serviceName . 'Binding', - 'endpoint' => $this->endpoint, - 'soapAction' => $soapaction, - 'style' => $style, - 'input' => array( - 'use' => $use, - 'namespace' => $namespace, - 'encodingStyle' => $encodingStyle, - 'message' => $name . 'Request', - 'parts' => $in), - 'output' => array( - 'use' => $use, - 'namespace' => $namespace, - 'encodingStyle' => $encodingStyle, - 'message' => $name . 'Response', - 'parts' => $out), - 'namespace' => $namespace, - 'transport' => 'http://schemas.xmlsoap.org/soap/http', - 'documentation' => $documentation); - // add portTypes - // add messages - if($in) - { - foreach($in as $pName => $pType) - { - if(strpos($pType,':')) { - $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType); - } - $this->messages[$name.'Request'][$pName] = $pType; - } - } else { - $this->messages[$name.'Request']= '0'; - } - if($out) - { - foreach($out as $pName => $pType) - { - if(strpos($pType,':')) { - $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType); - } - $this->messages[$name.'Response'][$pName] = $pType; - } - } else { - $this->messages[$name.'Response']= '0'; - } - return true; - } -} -?> -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_parser extends nusoap_base { - - var $xml = ''; - var $xml_encoding = ''; - var $method = ''; - var $root_struct = ''; - var $root_struct_name = ''; - var $root_struct_namespace = ''; - var $root_header = ''; - var $document = ''; // incoming SOAP body (text) - // determines where in the message we are (envelope,header,body,method) - var $status = ''; - var $position = 0; - var $depth = 0; - var $default_namespace = ''; - var $namespaces = array(); - var $message = array(); - var $parent = ''; - var $fault = false; - var $fault_code = ''; - var $fault_str = ''; - var $fault_detail = ''; - var $depth_array = array(); - var $debug_flag = true; - var $soapresponse = NULL; // parsed SOAP Body - var $soapheader = NULL; // parsed SOAP Header - var $responseHeaders = ''; // incoming SOAP headers (text) - var $body_position = 0; - // for multiref parsing: - // array of id => pos - var $ids = array(); - // array of id => hrefs => pos - var $multirefs = array(); - // toggle for auto-decoding element content - var $decode_utf8 = true; - - /** - * constructor that actually does the parsing - * - * @param string $xml SOAP message - * @param string $encoding character encoding scheme of message - * @param string $method method for which XML is parsed (unused?) - * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1 - * @access public - */ - function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){ - parent::nusoap_base(); - $this->xml = $xml; - $this->xml_encoding = $encoding; - $this->method = $method; - $this->decode_utf8 = $decode_utf8; - - // Check whether content has been read. - if(!empty($xml)){ - // Check XML encoding - $pos_xml = strpos($xml, '', $pos_xml + 2) - $pos_xml + 1); - if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) { - $xml_encoding = $res[1]; - if (strtoupper($xml_encoding) != $encoding) { - $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'"; - $this->debug($err); - if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') { - $this->setError($err); - return; - } - // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed - } else { - $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration'); - } - } else { - $this->debug('No encoding specified in XML declaration'); - } - } else { - $this->debug('No XML declaration'); - } - $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding); - // Create an XML parser - why not xml_parser_create_ns? - $this->parser = xml_parser_create($this->xml_encoding); - // Set the options for parsing the XML data. - //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); - xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); - xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding); - // Set the object for the parser. - xml_set_object($this->parser, $this); - // Set the element handlers for the parser. - xml_set_element_handler($this->parser, 'start_element','end_element'); - xml_set_character_data_handler($this->parser,'character_data'); - - // Parse the XML file. - if(!xml_parse($this->parser,$xml,true)){ - // Display an error message. - $err = sprintf('XML error parsing SOAP payload on line %d: %s', - xml_get_current_line_number($this->parser), - xml_error_string(xml_get_error_code($this->parser))); - $this->debug($err); - $this->debug("XML payload:\n" . $xml); - $this->setError($err); - } else { - $this->debug('in nusoap_parser ctor, message:'); - $this->appendDebug($this->varDump($this->message)); - $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name); - // get final value - $this->soapresponse = $this->message[$this->root_struct]['result']; - // get header value - if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){ - $this->soapheader = $this->message[$this->root_header]['result']; - } - // resolve hrefs/ids - if(sizeof($this->multirefs) > 0){ - foreach($this->multirefs as $id => $hrefs){ - $this->debug('resolving multirefs for id: '.$id); - $idVal = $this->buildVal($this->ids[$id]); - if (is_array($idVal) && isset($idVal['!id'])) { - unset($idVal['!id']); - } - foreach($hrefs as $refPos => $ref){ - $this->debug('resolving href at pos '.$refPos); - $this->multirefs[$id][$refPos] = $idVal; - } - } - } - } - xml_parser_free($this->parser); - } else { - $this->debug('xml was empty, didn\'t parse!'); - $this->setError('xml was empty, didn\'t parse!'); - } - } - - /** - * start-element handler - * - * @param resource $parser XML parser object - * @param string $name element name - * @param array $attrs associative array of attributes - * @access private - */ - function start_element($parser, $name, $attrs) { - // position in a total number of elements, starting from 0 - // update class level pos - $pos = $this->position++; - // and set mine - $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>''); - // depth = how many levels removed from root? - // set mine as current global depth and increment global depth value - $this->message[$pos]['depth'] = $this->depth++; - - // else add self as child to whoever the current parent is - if($pos != 0){ - $this->message[$this->parent]['children'] .= '|'.$pos; - } - // set my parent - $this->message[$pos]['parent'] = $this->parent; - // set self as current parent - $this->parent = $pos; - // set self as current value for this depth - $this->depth_array[$this->depth] = $pos; - // get element prefix - if(strpos($name,':')){ - // get ns prefix - $prefix = substr($name,0,strpos($name,':')); - // get unqualified name - $name = substr(strstr($name,':'),1); - } - // set status - if ($name == 'Envelope' && $this->status == '') { - $this->status = 'envelope'; - } elseif ($name == 'Header' && $this->status == 'envelope') { - $this->root_header = $pos; - $this->status = 'header'; - } elseif ($name == 'Body' && $this->status == 'envelope'){ - $this->status = 'body'; - $this->body_position = $pos; - // set method - } elseif($this->status == 'body' && $pos == ($this->body_position+1)) { - $this->status = 'method'; - $this->root_struct_name = $name; - $this->root_struct = $pos; - $this->message[$pos]['type'] = 'struct'; - $this->debug("found root struct $this->root_struct_name, pos $this->root_struct"); - } - // set my status - $this->message[$pos]['status'] = $this->status; - // set name - $this->message[$pos]['name'] = htmlspecialchars($name); - // set attrs - $this->message[$pos]['attrs'] = $attrs; - - // loop through atts, logging ns and type declarations - $attstr = ''; - foreach($attrs as $key => $value){ - $key_prefix = $this->getPrefix($key); - $key_localpart = $this->getLocalPart($key); - // if ns declarations, add to class level array of valid namespaces - if($key_prefix == 'xmlns'){ - if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){ - $this->XMLSchemaVersion = $value; - $this->namespaces['xsd'] = $this->XMLSchemaVersion; - $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance'; - } - $this->namespaces[$key_localpart] = $value; - // set method namespace - if($name == $this->root_struct_name){ - $this->methodNamespace = $value; - } - // if it's a type declaration, set type - } elseif($key_localpart == 'type'){ - if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') { - // do nothing: already processed arrayType - } else { - $value_prefix = $this->getPrefix($value); - $value_localpart = $this->getLocalPart($value); - $this->message[$pos]['type'] = $value_localpart; - $this->message[$pos]['typePrefix'] = $value_prefix; - if(isset($this->namespaces[$value_prefix])){ - $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix]; - } else if(isset($attrs['xmlns:'.$value_prefix])) { - $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix]; - } - // should do something here with the namespace of specified type? - } - } elseif($key_localpart == 'arrayType'){ - $this->message[$pos]['type'] = 'array'; - /* do arrayType ereg here - [1] arrayTypeValue ::= atype asize - [2] atype ::= QName rank* - [3] rank ::= '[' (',')* ']' - [4] asize ::= '[' length~ ']' - [5] length ::= nextDimension* Digit+ - [6] nextDimension ::= Digit+ ',' - */ - $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/'; - if(preg_match($expr,$value,$regs)){ - $this->message[$pos]['typePrefix'] = $regs[1]; - $this->message[$pos]['arrayTypePrefix'] = $regs[1]; - if (isset($this->namespaces[$regs[1]])) { - $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]]; - } else if (isset($attrs['xmlns:'.$regs[1]])) { - $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]]; - } - $this->message[$pos]['arrayType'] = $regs[2]; - $this->message[$pos]['arraySize'] = $regs[3]; - $this->message[$pos]['arrayCols'] = $regs[4]; - } - // specifies nil value (or not) - } elseif ($key_localpart == 'nil'){ - $this->message[$pos]['nil'] = ($value == 'true' || $value == '1'); - // some other attribute - } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') { - $this->message[$pos]['xattrs']['!' . $key] = $value; - } - - if ($key == 'xmlns') { - $this->default_namespace = $value; - } - // log id - if($key == 'id'){ - $this->ids[$value] = $pos; - } - // root - if($key_localpart == 'root' && $value == 1){ - $this->status = 'method'; - $this->root_struct_name = $name; - $this->root_struct = $pos; - $this->debug("found root struct $this->root_struct_name, pos $pos"); - } - // for doclit - $attstr .= " $key=\"$value\""; - } - // get namespace - must be done after namespace atts are processed - if(isset($prefix)){ - $this->message[$pos]['namespace'] = $this->namespaces[$prefix]; - $this->default_namespace = $this->namespaces[$prefix]; - } else { - $this->message[$pos]['namespace'] = $this->default_namespace; - } - if($this->status == 'header'){ - if ($this->root_header != $pos) { - $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>"; - } - } elseif($this->root_struct_name != ''){ - $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>"; - } - } - - /** - * end-element handler - * - * @param resource $parser XML parser object - * @param string $name element name - * @access private - */ - function end_element($parser, $name) { - // position of current element is equal to the last value left in depth_array for my depth - $pos = $this->depth_array[$this->depth--]; - - // get element prefix - if(strpos($name,':')){ - // get ns prefix - $prefix = substr($name,0,strpos($name,':')); - // get unqualified name - $name = substr(strstr($name,':'),1); - } - - // build to native type - if(isset($this->body_position) && $pos > $this->body_position){ - // deal w/ multirefs - if(isset($this->message[$pos]['attrs']['href'])){ - // get id - $id = substr($this->message[$pos]['attrs']['href'],1); - // add placeholder to href array - $this->multirefs[$id][$pos] = 'placeholder'; - // add set a reference to it as the result value - $this->message[$pos]['result'] =& $this->multirefs[$id][$pos]; - // build complexType values - } elseif($this->message[$pos]['children'] != ''){ - // if result has already been generated (struct/array) - if(!isset($this->message[$pos]['result'])){ - $this->message[$pos]['result'] = $this->buildVal($pos); - } - // build complexType values of attributes and possibly simpleContent - } elseif (isset($this->message[$pos]['xattrs'])) { - if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) { - $this->message[$pos]['xattrs']['!'] = null; - } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') { - if (isset($this->message[$pos]['type'])) { - $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - } else { - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - } else { - $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata']; - } - } - } - $this->message[$pos]['result'] = $this->message[$pos]['xattrs']; - // set value of simpleType (or nil complexType) - } else { - //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']); - if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) { - $this->message[$pos]['xattrs']['!'] = null; - } elseif (isset($this->message[$pos]['type'])) { - $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - } else { - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - } else { - $this->message[$pos]['result'] = $this->message[$pos]['cdata']; - } - } - - /* add value to parent's result, if parent is struct/array - $parent = $this->message[$pos]['parent']; - if($this->message[$parent]['type'] != 'map'){ - if(strtolower($this->message[$parent]['type']) == 'array'){ - $this->message[$parent]['result'][] = $this->message[$pos]['result']; - } else { - $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result']; - } - } - */ - } - } - - // for doclit - if($this->status == 'header'){ - if ($this->root_header != $pos) { - $this->responseHeaders .= ""; - } - } elseif($pos >= $this->root_struct){ - $this->document .= ""; - } - // switch status - if ($pos == $this->root_struct){ - $this->status = 'body'; - $this->root_struct_namespace = $this->message[$pos]['namespace']; - } elseif ($pos == $this->root_header) { - $this->status = 'envelope'; - } elseif ($name == 'Body' && $this->status == 'body') { - $this->status = 'envelope'; - } elseif ($name == 'Header' && $this->status == 'header') { // will never happen - $this->status = 'envelope'; - } elseif ($name == 'Envelope' && $this->status == 'envelope') { - $this->status = ''; - } - // set parent back to my parent - $this->parent = $this->message[$pos]['parent']; - } - - /** - * element content handler - * - * @param resource $parser XML parser object - * @param string $data element content - * @access private - */ - function character_data($parser, $data){ - $pos = $this->depth_array[$this->depth]; - if ($this->xml_encoding=='UTF-8'){ - // TODO: add an option to disable this for folks who want - // raw UTF-8 that, e.g., might not map to iso-8859-1 - // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1"); - if($this->decode_utf8){ - $data = utf8_decode($data); - } - } - $this->message[$pos]['cdata'] .= $data; - // for doclit - if($this->status == 'header'){ - $this->responseHeaders .= $data; - } else { - $this->document .= $data; - } - } - - /** - * get the parsed message (SOAP Body) - * - * @return mixed - * @access public - * @deprecated use get_soapbody instead - */ - function get_response(){ - return $this->soapresponse; - } - - /** - * get the parsed SOAP Body (NULL if there was none) - * - * @return mixed - * @access public - */ - function get_soapbody(){ - return $this->soapresponse; - } - - /** - * get the parsed SOAP Header (NULL if there was none) - * - * @return mixed - * @access public - */ - function get_soapheader(){ - return $this->soapheader; - } - - /** - * get the unparsed SOAP Header - * - * @return string XML or empty if no Header - * @access public - */ - function getHeaders(){ - return $this->responseHeaders; - } - - /** - * decodes simple types into PHP variables - * - * @param string $value value to decode - * @param string $type XML type to decode - * @param string $typens XML type namespace to decode - * @return mixed PHP value - * @access private - */ - function decodeSimple($value, $type, $typens) { - // TODO: use the namespace! - if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') { - return (string) $value; - } - if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') { - return (int) $value; - } - if ($type == 'float' || $type == 'double' || $type == 'decimal') { - return (double) $value; - } - if ($type == 'boolean') { - if (strtolower($value) == 'false' || strtolower($value) == 'f') { - return false; - } - return (boolean) $value; - } - if ($type == 'base64' || $type == 'base64Binary') { - $this->debug('Decode base64 value'); - return base64_decode($value); - } - // obscure numeric types - if ($type == 'nonPositiveInteger' || $type == 'negativeInteger' - || $type == 'nonNegativeInteger' || $type == 'positiveInteger' - || $type == 'unsignedInt' - || $type == 'unsignedShort' || $type == 'unsignedByte') { - return (int) $value; - } - // bogus: parser treats array with no elements as a simple type - if ($type == 'array') { - return array(); - } - // everything else - return (string) $value; - } - - /** - * builds response structures for compound values (arrays/structs) - * and scalars - * - * @param integer $pos position in node tree - * @return mixed PHP value - * @access private - */ - function buildVal($pos){ - if(!isset($this->message[$pos]['type'])){ - $this->message[$pos]['type'] = ''; - } - $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']); - // if there are children... - if($this->message[$pos]['children'] != ''){ - $this->debug('in buildVal, there are children'); - $children = explode('|',$this->message[$pos]['children']); - array_shift($children); // knock off empty - // md array - if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){ - $r=0; // rowcount - $c=0; // colcount - foreach($children as $child_pos){ - $this->debug("in buildVal, got an MD array element: $r, $c"); - $params[$r][] = $this->message[$child_pos]['result']; - $c++; - if($c == $this->message[$pos]['arrayCols']){ - $c = 0; - $r++; - } - } - // array - } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){ - $this->debug('in buildVal, adding array '.$this->message[$pos]['name']); - foreach($children as $child_pos){ - $params[] = &$this->message[$child_pos]['result']; - } - // apache Map type: java hashtable - } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){ - $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']); - foreach($children as $child_pos){ - $kv = explode("|",$this->message[$child_pos]['children']); - $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result']; - } - // generic compound type - //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') { - } else { - // Apache Vector type: treat as an array - $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']); - if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') { - $notstruct = 1; - } else { - $notstruct = 0; - } - // - foreach($children as $child_pos){ - if($notstruct){ - $params[] = &$this->message[$child_pos]['result']; - } else { - if (isset($params[$this->message[$child_pos]['name']])) { - // de-serialize repeated element name into an array - if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) { - $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]); - } - $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result']; - } else { - $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result']; - } - } - } - } - if (isset($this->message[$pos]['xattrs'])) { - $this->debug('in buildVal, handling attributes'); - foreach ($this->message[$pos]['xattrs'] as $n => $v) { - $params[$n] = $v; - } - } - // handle simpleContent - if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') { - $this->debug('in buildVal, handling simpleContent'); - if (isset($this->message[$pos]['type'])) { - $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - } else { - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - } else { - $params['!'] = $this->message[$pos]['cdata']; - } - } - } - $ret = is_array($params) ? $params : array(); - $this->debug('in buildVal, return:'); - $this->appendDebug($this->varDump($ret)); - return $ret; - } else { - $this->debug('in buildVal, no children, building scalar'); - $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : ''; - if (isset($this->message[$pos]['type'])) { - $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : ''); - $this->debug("in buildVal, return: $ret"); - return $ret; - } - $parent = $this->message[$pos]['parent']; - if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { - $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : ''); - $this->debug("in buildVal, return: $ret"); - return $ret; - } - $ret = $this->message[$pos]['cdata']; - $this->debug("in buildVal, return: $ret"); - return $ret; - } - } -} - -/** - * Backward compatibility - */ -class soap_parser extends nusoap_parser { -} - -?>call( string methodname [ ,array parameters] ); -* -* // bye bye client -* unset($soapclient); -* -* @author Dietrich Ayala -* @author Scott Nichol -* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_client extends nusoap_base { - - var $username = ''; // Username for HTTP authentication - var $password = ''; // Password for HTTP authentication - var $authtype = ''; // Type of HTTP authentication - var $certRequest = array(); // Certificate for HTTP SSL authentication - var $requestHeaders = false; // SOAP headers in request (text) - var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text) - var $responseHeader = NULL; // SOAP Header from response (parsed) - var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text) - var $endpoint; - var $forceEndpoint = ''; // overrides WSDL endpoint - var $proxyhost = ''; - var $proxyport = ''; - var $proxyusername = ''; - var $proxypassword = ''; - var $portName = ''; // port name to use in WSDL - var $xml_encoding = ''; // character set encoding of incoming (response) messages - var $http_encoding = false; - var $timeout = 0; // HTTP connection timeout - var $response_timeout = 30; // HTTP response timeout - var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error - var $persistentConnection = false; - var $defaultRpcParams = false; // This is no longer used - var $request = ''; // HTTP request - var $response = ''; // HTTP response - var $responseData = ''; // SOAP payload of response - var $cookies = array(); // Cookies from response or for request - var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode() - var $operations = array(); // WSDL operations, empty for WSDL initialization error - var $curl_options = array(); // User-specified cURL options - var $bindingType = ''; // WSDL operation binding type - var $use_curl = false; // whether to always try to use cURL - - /* - * fault related variables - */ - /** - * @var fault - * @access public - */ - var $fault; - /** - * @var faultcode - * @access public - */ - var $faultcode; - /** - * @var faultstring - * @access public - */ - var $faultstring; - /** - * @var faultdetail - * @access public - */ - var $faultdetail; - - /** - * constructor - * - * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object) - * @param mixed $wsdl optional, set to 'wsdl' or true if using WSDL - * @param string $proxyhost optional - * @param string $proxyport optional - * @param string $proxyusername optional - * @param string $proxypassword optional - * @param integer $timeout set the connection timeout - * @param integer $response_timeout set the response timeout - * @param string $portName optional portName in WSDL document - * @access public - */ - function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = ''){ - parent::nusoap_base(); - $this->endpoint = $endpoint; - $this->proxyhost = $proxyhost; - $this->proxyport = $proxyport; - $this->proxyusername = $proxyusername; - $this->proxypassword = $proxypassword; - $this->timeout = $timeout; - $this->response_timeout = $response_timeout; - $this->portName = $portName; - - $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout"); - $this->appendDebug('endpoint=' . $this->varDump($endpoint)); - - // make values - if($wsdl){ - if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) { - $this->wsdl = $endpoint; - $this->endpoint = $this->wsdl->wsdl; - $this->wsdlFile = $this->endpoint; - $this->debug('existing wsdl instance created from ' . $this->endpoint); - $this->checkWSDL(); - } else { - $this->wsdlFile = $this->endpoint; - $this->wsdl = null; - $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint); - } - $this->endpointType = 'wsdl'; - } else { - $this->debug("instantiate SOAP with endpoint at $endpoint"); - $this->endpointType = 'soap'; - } - } - - /** - * calls method, returns PHP native type - * - * @param string $operation SOAP server URL or path - * @param mixed $params An array, associative or simple, of the parameters - * for the method call, or a string that is the XML - * for the call. For rpc style, this call will - * wrap the XML in a tag named after the method, as - * well as the SOAP Envelope and Body. For document - * style, this will only wrap with the Envelope and Body. - * IMPORTANT: when using an array with document style, - * in which case there - * is really one parameter, the root of the fragment - * used in the call, which encloses what programmers - * normally think of parameters. A parameter array - * *must* include the wrapper. - * @param string $namespace optional method namespace (WSDL can override) - * @param string $soapAction optional SOAPAction value (WSDL can override) - * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array - * @param boolean $rpcParams optional (no longer used) - * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override) - * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override) - * @return mixed response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors - * @access public - */ - function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){ - $this->operation = $operation; - $this->fault = false; - $this->setError(''); - $this->request = ''; - $this->response = ''; - $this->responseData = ''; - $this->faultstring = ''; - $this->faultcode = ''; - $this->opData = array(); - - $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType"); - $this->appendDebug('params=' . $this->varDump($params)); - $this->appendDebug('headers=' . $this->varDump($headers)); - if ($headers) { - $this->requestHeaders = $headers; - } - if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) { - $this->loadWSDL(); - if ($this->getError()) - return false; - } - // serialize parameters - if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){ - // use WSDL for operation - $this->opData = $opData; - $this->debug("found operation"); - $this->appendDebug('opData=' . $this->varDump($opData)); - if (isset($opData['soapAction'])) { - $soapAction = $opData['soapAction']; - } - if (! $this->forceEndpoint) { - $this->endpoint = $opData['endpoint']; - } else { - $this->endpoint = $this->forceEndpoint; - } - $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace; - $style = $opData['style']; - $use = $opData['input']['use']; - // add ns to ns array - if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){ - $nsPrefix = 'ns' . rand(1000, 9999); - $this->wsdl->namespaces[$nsPrefix] = $namespace; - } - $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace); - // serialize payload - if (is_string($params)) { - $this->debug("serializing param string for WSDL operation $operation"); - $payload = $params; - } elseif (is_array($params)) { - $this->debug("serializing param array for WSDL operation $operation"); - $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType); - } else { - $this->debug('params must be array or string'); - $this->setError('params must be array or string'); - return false; - } - $usedNamespaces = $this->wsdl->usedNamespaces; - if (isset($opData['input']['encodingStyle'])) { - $encodingStyle = $opData['input']['encodingStyle']; - } else { - $encodingStyle = ''; - } - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - if ($errstr = $this->wsdl->getError()) { - $this->debug('got wsdl error: '.$errstr); - $this->setError('wsdl error: '.$errstr); - return false; - } - } elseif($this->endpointType == 'wsdl') { - // operation not in WSDL - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->setError('operation '.$operation.' not present in WSDL.'); - $this->debug("operation '$operation' not present in WSDL."); - return false; - } else { - // no WSDL - //$this->namespaces['ns1'] = $namespace; - $nsPrefix = 'ns' . rand(1000, 9999); - // serialize - $payload = ''; - if (is_string($params)) { - $this->debug("serializing param string for operation $operation"); - $payload = $params; - } elseif (is_array($params)) { - $this->debug("serializing param array for operation $operation"); - foreach($params as $k => $v){ - $payload .= $this->serialize_val($v,$k,false,false,false,false,$use); - } - } else { - $this->debug('params must be array or string'); - $this->setError('params must be array or string'); - return false; - } - $usedNamespaces = array(); - if ($use == 'encoded') { - $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; - } else { - $encodingStyle = ''; - } - } - // wrap RPC calls with method element - if ($style == 'rpc') { - if ($use == 'literal') { - $this->debug("wrapping RPC request with literal method element"); - if ($namespace) { - // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace - $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" . - $payload . - ""; - } else { - $payload = "<$operation>" . $payload . ""; - } - } else { - $this->debug("wrapping RPC request with encoded method element"); - if ($namespace) { - $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" . - $payload . - ""; - } else { - $payload = "<$operation>" . - $payload . - ""; - } - } - } - // serialize envelope - $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle); - $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle"); - $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000)); - // send - $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout); - if($errstr = $this->getError()){ - $this->debug('Error: '.$errstr); - return false; - } else { - $this->return = $return; - $this->debug('sent message successfully and got a(n) '.gettype($return)); - $this->appendDebug('return=' . $this->varDump($return)); - - // fault? - if(is_array($return) && isset($return['faultcode'])){ - $this->debug('got fault'); - $this->setError($return['faultcode'].': '.$return['faultstring']); - $this->fault = true; - foreach($return as $k => $v){ - $this->$k = $v; - $this->debug("$k = $v
    "); - } - return $return; - } elseif ($style == 'document') { - // NOTE: if the response is defined to have multiple parts (i.e. unwrapped), - // we are only going to return the first part here...sorry about that - return $return; - } else { - // array of return values - if(is_array($return)){ - // multiple 'out' parameters, which we return wrapped up - // in the array - if(sizeof($return) > 1){ - return $return; - } - // single 'out' parameter (normally the return value) - $return = array_shift($return); - $this->debug('return shifted value: '); - $this->appendDebug($this->varDump($return)); - return $return; - // nothing returned (ie, echoVoid) - } else { - return ""; - } - } - } - } - - /** - * check WSDL passed as an instance or pulled from an endpoint - * - * @access private - */ - function checkWSDL() { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->debug('checkWSDL'); - // catch errors - if ($errstr = $this->wsdl->getError()) { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->debug('got wsdl error: '.$errstr); - $this->setError('wsdl error: '.$errstr); - } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->bindingType = 'soap'; - $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType); - } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->bindingType = 'soap12'; - $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType); - $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************'); - } else { - $this->appendDebug($this->wsdl->getDebug()); - $this->wsdl->clearDebug(); - $this->debug('getOperations returned false'); - $this->setError('no operations defined in the WSDL document!'); - } - } - - /** - * instantiate wsdl object and parse wsdl file - * - * @access public - */ - function loadWSDL() { - $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile); - $this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl); - $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest); - $this->wsdl->fetchWSDL($this->wsdlFile); - $this->checkWSDL(); - } - - /** - * get available data pertaining to an operation - * - * @param string $operation operation name - * @return array array of data pertaining to the operation - * @access public - */ - function getOperationData($operation){ - if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) { - $this->loadWSDL(); - if ($this->getError()) - return false; - } - if(isset($this->operations[$operation])){ - return $this->operations[$operation]; - } - $this->debug("No data for operation: $operation"); - } - - /** - * send the SOAP message - * - * Note: if the operation has multiple return values - * the return value of this method will be an array - * of those values. - * - * @param string $msg a SOAPx4 soapmsg object - * @param string $soapaction SOAPAction value - * @param integer $timeout set connection timeout in seconds - * @param integer $response_timeout set response timeout in seconds - * @return mixed native PHP types. - * @access private - */ - function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) { - $this->checkCookies(); - // detect transport - switch(true){ - // http(s) - case preg_match('/^http/',$this->endpoint): - $this->debug('transporting via HTTP'); - if($this->persistentConnection == true && is_object($this->persistentConnection)){ - $http =& $this->persistentConnection; - } else { - $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl); - if ($this->persistentConnection) { - $http->usePersistentConnection(); - } - } - $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset()); - $http->setSOAPAction($soapaction); - if($this->proxyhost && $this->proxyport){ - $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword); - } - if($this->authtype != '') { - $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest); - } - if($this->http_encoding != ''){ - $http->setEncoding($this->http_encoding); - } - $this->debug('sending message, length='.strlen($msg)); - if(preg_match('/^http:/',$this->endpoint)){ - //if(strpos($this->endpoint,'http:')){ - $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies); - } elseif(preg_match('/^https/',$this->endpoint)){ - //} elseif(strpos($this->endpoint,'https:')){ - //if(phpversion() == '4.3.0-dev'){ - //$response = $http->send($msg,$timeout,$response_timeout); - //$this->request = $http->outgoing_payload; - //$this->response = $http->incoming_payload; - //} else - $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies); - } else { - $this->setError('no http/s in endpoint url'); - } - $this->request = $http->outgoing_payload; - $this->response = $http->incoming_payload; - $this->appendDebug($http->getDebug()); - $this->UpdateCookies($http->incoming_cookies); - - // save transport object if using persistent connections - if ($this->persistentConnection) { - $http->clearDebug(); - if (!is_object($this->persistentConnection)) { - $this->persistentConnection = $http; - } - } - - if($err = $http->getError()){ - $this->setError('HTTP Error: '.$err); - return false; - } elseif($this->getError()){ - return false; - } else { - $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']); - return $this->parseResponse($http->incoming_headers, $this->responseData); - } - break; - default: - $this->setError('no transport found, or selected transport is not yet supported!'); - return false; - break; - } - } - - /** - * processes SOAP message returned from server - * - * @param array $headers The HTTP headers - * @param string $data unprocessed response data from server - * @return mixed value of the message, decoded into a PHP type - * @access private - */ - function parseResponse($headers, $data) { - $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:'); - $this->appendDebug($this->varDump($headers)); - if (!isset($headers['content-type'])) { - $this->setError('Response not of type text/xml (no content-type header)'); - return false; - } - if (!strstr($headers['content-type'], 'text/xml')) { - $this->setError('Response not of type text/xml: ' . $headers['content-type']); - return false; - } - if (strpos($headers['content-type'], '=')) { - $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1)); - $this->debug('Got response encoding: ' . $enc); - if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){ - $this->xml_encoding = strtoupper($enc); - } else { - $this->xml_encoding = 'US-ASCII'; - } - } else { - // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 - $this->xml_encoding = 'ISO-8859-1'; - } - $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser'); - $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8); - // add parser debug data to our debug - $this->appendDebug($parser->getDebug()); - // if parse errors - if($errstr = $parser->getError()){ - $this->setError( $errstr); - // destroy the parser object - unset($parser); - return false; - } else { - // get SOAP headers - $this->responseHeaders = $parser->getHeaders(); - // get SOAP headers - $this->responseHeader = $parser->get_soapheader(); - // get decoded message - $return = $parser->get_soapbody(); - // add document for doclit support - $this->document = $parser->document; - // destroy the parser object - unset($parser); - // return decode message - return $return; - } - } - - /** - * sets user-specified cURL options - * - * @param mixed $option The cURL option (always integer?) - * @param mixed $value The cURL option value - * @access public - */ - function setCurlOption($option, $value) { - $this->debug("setCurlOption option=$option, value="); - $this->appendDebug($this->varDump($value)); - $this->curl_options[$option] = $value; - } - - /** - * sets the SOAP endpoint, which can override WSDL - * - * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override - * @access public - */ - function setEndpoint($endpoint) { - $this->debug("setEndpoint(\"$endpoint\")"); - $this->forceEndpoint = $endpoint; - } - - /** - * set the SOAP headers - * - * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers - * @access public - */ - function setHeaders($headers){ - $this->debug("setHeaders headers="); - $this->appendDebug($this->varDump($headers)); - $this->requestHeaders = $headers; - } - - /** - * get the SOAP response headers (namespace resolution incomplete) - * - * @return string - * @access public - */ - function getHeaders(){ - return $this->responseHeaders; - } - - /** - * get the SOAP response Header (parsed) - * - * @return mixed - * @access public - */ - function getHeader(){ - return $this->responseHeader; - } - - /** - * set proxy info here - * - * @param string $proxyhost - * @param string $proxyport - * @param string $proxyusername - * @param string $proxypassword - * @access public - */ - function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') { - $this->proxyhost = $proxyhost; - $this->proxyport = $proxyport; - $this->proxyusername = $proxyusername; - $this->proxypassword = $proxypassword; - } - - /** - * if authenticating, set user credentials here - * - * @param string $username - * @param string $password - * @param string $authtype (basic|digest|certificate|ntlm) - * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) - * @access public - */ - function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) { - $this->debug("setCredentials username=$username authtype=$authtype certRequest="); - $this->appendDebug($this->varDump($certRequest)); - $this->username = $username; - $this->password = $password; - $this->authtype = $authtype; - $this->certRequest = $certRequest; - } - - /** - * use HTTP encoding - * - * @param string $enc HTTP encoding - * @access public - */ - function setHTTPEncoding($enc='gzip, deflate'){ - $this->debug("setHTTPEncoding(\"$enc\")"); - $this->http_encoding = $enc; - } - - /** - * Set whether to try to use cURL connections if possible - * - * @param boolean $use Whether to try to use cURL - * @access public - */ - function setUseCURL($use) { - $this->debug("setUseCURL($use)"); - $this->use_curl = $use; - } - - /** - * use HTTP persistent connections if possible - * - * @access public - */ - function useHTTPPersistentConnection(){ - $this->debug("useHTTPPersistentConnection"); - $this->persistentConnection = true; - } - - /** - * gets the default RPC parameter setting. - * If true, default is that call params are like RPC even for document style. - * Each call() can override this value. - * - * This is no longer used. - * - * @return boolean - * @access public - * @deprecated - */ - function getDefaultRpcParams() { - return $this->defaultRpcParams; - } - - /** - * sets the default RPC parameter setting. - * If true, default is that call params are like RPC even for document style - * Each call() can override this value. - * - * This is no longer used. - * - * @param boolean $rpcParams - * @access public - * @deprecated - */ - function setDefaultRpcParams($rpcParams) { - $this->defaultRpcParams = $rpcParams; - } - - /** - * dynamically creates an instance of a proxy class, - * allowing user to directly call methods from wsdl - * - * @return object soap_proxy object - * @access public - */ - function getProxy() { - $r = rand(); - $evalStr = $this->_getProxyClassCode($r); - //$this->debug("proxy class: $evalStr"); - if ($this->getError()) { - $this->debug("Error from _getProxyClassCode, so return NULL"); - return null; - } - // eval the class - eval($evalStr); - // instantiate proxy object - eval("\$proxy = new nusoap_proxy_$r('');"); - // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice - $proxy->endpointType = 'wsdl'; - $proxy->wsdlFile = $this->wsdlFile; - $proxy->wsdl = $this->wsdl; - $proxy->operations = $this->operations; - $proxy->defaultRpcParams = $this->defaultRpcParams; - // transfer other state - $proxy->soap_defencoding = $this->soap_defencoding; - $proxy->username = $this->username; - $proxy->password = $this->password; - $proxy->authtype = $this->authtype; - $proxy->certRequest = $this->certRequest; - $proxy->requestHeaders = $this->requestHeaders; - $proxy->endpoint = $this->endpoint; - $proxy->forceEndpoint = $this->forceEndpoint; - $proxy->proxyhost = $this->proxyhost; - $proxy->proxyport = $this->proxyport; - $proxy->proxyusername = $this->proxyusername; - $proxy->proxypassword = $this->proxypassword; - $proxy->http_encoding = $this->http_encoding; - $proxy->timeout = $this->timeout; - $proxy->response_timeout = $this->response_timeout; - $proxy->persistentConnection = &$this->persistentConnection; - $proxy->decode_utf8 = $this->decode_utf8; - $proxy->curl_options = $this->curl_options; - $proxy->bindingType = $this->bindingType; - $proxy->use_curl = $this->use_curl; - return $proxy; - } - - /** - * dynamically creates proxy class code - * - * @return string PHP/NuSOAP code for the proxy class - * @access private - */ - function _getProxyClassCode($r) { - $this->debug("in getProxy endpointType=$this->endpointType"); - $this->appendDebug("wsdl=" . $this->varDump($this->wsdl)); - if ($this->endpointType != 'wsdl') { - $evalStr = 'A proxy can only be created for a WSDL client'; - $this->setError($evalStr); - $evalStr = "echo \"$evalStr\";"; - return $evalStr; - } - if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) { - $this->loadWSDL(); - if ($this->getError()) { - return "echo \"" . $this->getError() . "\";"; - } - } - $evalStr = ''; - foreach ($this->operations as $operation => $opData) { - if ($operation != '') { - // create param string and param comment string - if (sizeof($opData['input']['parts']) > 0) { - $paramStr = ''; - $paramArrayStr = ''; - $paramCommentStr = ''; - foreach ($opData['input']['parts'] as $name => $type) { - $paramStr .= "\$$name, "; - $paramArrayStr .= "'$name' => \$$name, "; - $paramCommentStr .= "$type \$$name, "; - } - $paramStr = substr($paramStr, 0, strlen($paramStr)-2); - $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2); - $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2); - } else { - $paramStr = ''; - $paramArrayStr = ''; - $paramCommentStr = 'void'; - } - $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace']; - $evalStr .= "// $paramCommentStr - function " . str_replace('.', '__', $operation) . "($paramStr) { - \$params = array($paramArrayStr); - return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."'); - } - "; - unset($paramStr); - unset($paramCommentStr); - } - } - $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client { - '.$evalStr.' -}'; - return $evalStr; - } - - /** - * dynamically creates proxy class code - * - * @return string PHP/NuSOAP code for the proxy class - * @access public - */ - function getProxyClassCode() { - $r = rand(); - return $this->_getProxyClassCode($r); - } - - /** - * gets the HTTP body for the current request. - * - * @param string $soapmsg The SOAP payload - * @return string The HTTP body, which includes the SOAP payload - * @access private - */ - function getHTTPBody($soapmsg) { - return $soapmsg; - } - - /** - * gets the HTTP content type for the current request. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type for the current request. - * @access private - */ - function getHTTPContentType() { - return 'text/xml'; - } - - /** - * gets the HTTP content type charset for the current request. - * returns false for non-text content types. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type charset for the current request. - * @access private - */ - function getHTTPContentTypeCharset() { - return $this->soap_defencoding; - } - - /* - * whether or not parser should decode utf8 element content - * - * @return always returns true - * @access public - */ - function decodeUTF8($bool){ - $this->decode_utf8 = $bool; - return true; - } - - /** - * adds a new Cookie into $this->cookies array - * - * @param string $name Cookie Name - * @param string $value Cookie Value - * @return boolean if cookie-set was successful returns true, else false - * @access public - */ - function setCookie($name, $value) { - if (strlen($name) == 0) { - return false; - } - $this->cookies[] = array('name' => $name, 'value' => $value); - return true; - } - - /** - * gets all Cookies - * - * @return array with all internal cookies - * @access public - */ - function getCookies() { - return $this->cookies; - } - - /** - * checks all Cookies and delete those which are expired - * - * @return boolean always return true - * @access private - */ - function checkCookies() { - if (sizeof($this->cookies) == 0) { - return true; - } - $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies'); - $curr_cookies = $this->cookies; - $this->cookies = array(); - foreach ($curr_cookies as $cookie) { - if (! is_array($cookie)) { - $this->debug('Remove cookie that is not an array'); - continue; - } - if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) { - if (strtotime($cookie['expires']) > time()) { - $this->cookies[] = $cookie; - } else { - $this->debug('Remove expired cookie ' . $cookie['name']); - } - } else { - $this->cookies[] = $cookie; - } - } - $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array'); - return true; - } - - /** - * updates the current cookies with a new set - * - * @param array $cookies new cookies with which to update current ones - * @return boolean always return true - * @access private - */ - function UpdateCookies($cookies) { - if (sizeof($this->cookies) == 0) { - // no existing cookies: take whatever is new - if (sizeof($cookies) > 0) { - $this->debug('Setting new cookie(s)'); - $this->cookies = $cookies; - } - return true; - } - if (sizeof($cookies) == 0) { - // no new cookies: keep what we've got - return true; - } - // merge - foreach ($cookies as $newCookie) { - if (!is_array($newCookie)) { - continue; - } - if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) { - continue; - } - $newName = $newCookie['name']; - - $found = false; - for ($i = 0; $i < count($this->cookies); $i++) { - $cookie = $this->cookies[$i]; - if (!is_array($cookie)) { - continue; - } - if (!isset($cookie['name'])) { - continue; - } - if ($newName != $cookie['name']) { - continue; - } - $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN'; - $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN'; - if ($newDomain != $domain) { - continue; - } - $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH'; - $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH'; - if ($newPath != $path) { - continue; - } - $this->cookies[$i] = $newCookie; - $found = true; - $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']); - break; - } - if (! $found) { - $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']); - $this->cookies[] = $newCookie; - } - } - return true; - } -} - -if (!extension_loaded('soap')) { - /** - * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded. - */ - class soapclient extends nusoap_client { - } -} -?> diff --git a/lib/nusoap/nusoapmime.php b/lib/nusoap/nusoapmime.php deleted file mode 100644 index 649386306..000000000 --- a/lib/nusoap/nusoapmime.php +++ /dev/null @@ -1,501 +0,0 @@ - -* @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list -* @version $Id: nusoapmime.php,v 1.13 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_client_mime extends nusoap_client { - /** - * @var array Each array element in the return is an associative array with keys - * data, filename, contenttype, cid - * @access private - */ - var $requestAttachments = array(); - /** - * @var array Each array element in the return is an associative array with keys - * data, filename, contenttype, cid - * @access private - */ - var $responseAttachments; - /** - * @var string - * @access private - */ - var $mimeContentType; - - /** - * adds a MIME attachment to the current request. - * - * If the $data parameter contains an empty string, this method will read - * the contents of the file named by the $filename parameter. - * - * If the $cid parameter is false, this method will generate the cid. - * - * @param string $data The data of the attachment - * @param string $filename The filename of the attachment (default is empty string) - * @param string $contenttype The MIME Content-Type of the attachment (default is application/octet-stream) - * @param string $cid The content-id (cid) of the attachment (default is false) - * @return string The content-id (cid) of the attachment - * @access public - */ - function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) { - if (! $cid) { - $cid = md5(uniqid(time())); - } - - $info['data'] = $data; - $info['filename'] = $filename; - $info['contenttype'] = $contenttype; - $info['cid'] = $cid; - - $this->requestAttachments[] = $info; - - return $cid; - } - - /** - * clears the MIME attachments for the current request. - * - * @access public - */ - function clearAttachments() { - $this->requestAttachments = array(); - } - - /** - * gets the MIME attachments from the current response. - * - * Each array element in the return is an associative array with keys - * data, filename, contenttype, cid. These keys correspond to the parameters - * for addAttachment. - * - * @return array The attachments. - * @access public - */ - function getAttachments() { - return $this->responseAttachments; - } - - /** - * gets the HTTP body for the current request. - * - * @param string $soapmsg The SOAP payload - * @return string The HTTP body, which includes the SOAP payload - * @access private - */ - function getHTTPBody($soapmsg) { - if (count($this->requestAttachments) > 0) { - $params['content_type'] = 'multipart/related; type="text/xml"'; - $mimeMessage = new Mail_mimePart('', $params); - unset($params); - - $params['content_type'] = 'text/xml'; - $params['encoding'] = '8bit'; - $params['charset'] = $this->soap_defencoding; - $mimeMessage->addSubpart($soapmsg, $params); - - foreach ($this->requestAttachments as $att) { - unset($params); - - $params['content_type'] = $att['contenttype']; - $params['encoding'] = 'base64'; - $params['disposition'] = 'attachment'; - $params['dfilename'] = $att['filename']; - $params['cid'] = $att['cid']; - - if ($att['data'] == '' && $att['filename'] <> '') { - if ($fd = fopen($att['filename'], 'rb')) { - $data = fread($fd, filesize($att['filename'])); - fclose($fd); - } else { - $data = ''; - } - $mimeMessage->addSubpart($data, $params); - } else { - $mimeMessage->addSubpart($att['data'], $params); - } - } - - $output = $mimeMessage->encode(); - $mimeHeaders = $output['headers']; - - foreach ($mimeHeaders as $k => $v) { - $this->debug("MIME header $k: $v"); - if (strtolower($k) == 'content-type') { - // PHP header() seems to strip leading whitespace starting - // the second line, so force everything to one line - $this->mimeContentType = str_replace("\r\n", " ", $v); - } - } - - return $output['body']; - } - - return parent::getHTTPBody($soapmsg); - } - - /** - * gets the HTTP content type for the current request. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type for the current request. - * @access private - */ - function getHTTPContentType() { - if (count($this->requestAttachments) > 0) { - return $this->mimeContentType; - } - return parent::getHTTPContentType(); - } - - /** - * gets the HTTP content type charset for the current request. - * returns false for non-text content types. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type charset for the current request. - * @access private - */ - function getHTTPContentTypeCharset() { - if (count($this->requestAttachments) > 0) { - return false; - } - return parent::getHTTPContentTypeCharset(); - } - - /** - * processes SOAP message returned from server - * - * @param array $headers The HTTP headers - * @param string $data unprocessed response data from server - * @return mixed value of the message, decoded into a PHP type - * @access private - */ - function parseResponse($headers, $data) { - $this->debug('Entering parseResponse() for payload of length ' . strlen($data) . ' and type of ' . $headers['content-type']); - $this->responseAttachments = array(); - if (strstr($headers['content-type'], 'multipart/related')) { - $this->debug('Decode multipart/related'); - $input = ''; - foreach ($headers as $k => $v) { - $input .= "$k: $v\r\n"; - } - $params['input'] = $input . "\r\n" . $data; - $params['include_bodies'] = true; - $params['decode_bodies'] = true; - $params['decode_headers'] = true; - - $structure = Mail_mimeDecode::decode($params); - - foreach ($structure->parts as $part) { - if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) { - $this->debug('Have root part of type ' . $part->headers['content-type']); - $root = $part->body; - $return = parent::parseResponse($part->headers, $part->body); - } else { - $this->debug('Have an attachment of type ' . $part->headers['content-type']); - $info['data'] = $part->body; - $info['filename'] = isset($part->d_parameters['filename']) ? $part->d_parameters['filename'] : ''; - $info['contenttype'] = $part->headers['content-type']; - $info['cid'] = $part->headers['content-id']; - $this->responseAttachments[] = $info; - } - } - - if (isset($return)) { - $this->responseData = $root; - return $return; - } - - $this->setError('No root part found in multipart/related content'); - return ''; - } - $this->debug('Not multipart/related'); - return parent::parseResponse($headers, $data); - } -} - -/* - * For backwards compatiblity, define soapclientmime unless the PHP SOAP extension is loaded. - */ -if (!extension_loaded('soap')) { - class soapclientmime extends nusoap_client_mime { - } -} - -/** -* nusoap_server_mime server supporting MIME attachments defined at -* http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library. -* -* @author Scott Nichol -* @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list -* @version $Id: nusoapmime.php,v 1.13 2010/04/26 20:15:08 snichol Exp $ -* @access public -*/ -class nusoap_server_mime extends nusoap_server { - /** - * @var array Each array element in the return is an associative array with keys - * data, filename, contenttype, cid - * @access private - */ - var $requestAttachments = array(); - /** - * @var array Each array element in the return is an associative array with keys - * data, filename, contenttype, cid - * @access private - */ - var $responseAttachments; - /** - * @var string - * @access private - */ - var $mimeContentType; - - /** - * adds a MIME attachment to the current response. - * - * If the $data parameter contains an empty string, this method will read - * the contents of the file named by the $filename parameter. - * - * If the $cid parameter is false, this method will generate the cid. - * - * @param string $data The data of the attachment - * @param string $filename The filename of the attachment (default is empty string) - * @param string $contenttype The MIME Content-Type of the attachment (default is application/octet-stream) - * @param string $cid The content-id (cid) of the attachment (default is false) - * @return string The content-id (cid) of the attachment - * @access public - */ - function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) { - if (! $cid) { - $cid = md5(uniqid(time())); - } - - $info['data'] = $data; - $info['filename'] = $filename; - $info['contenttype'] = $contenttype; - $info['cid'] = $cid; - - $this->responseAttachments[] = $info; - - return $cid; - } - - /** - * clears the MIME attachments for the current response. - * - * @access public - */ - function clearAttachments() { - $this->responseAttachments = array(); - } - - /** - * gets the MIME attachments from the current request. - * - * Each array element in the return is an associative array with keys - * data, filename, contenttype, cid. These keys correspond to the parameters - * for addAttachment. - * - * @return array The attachments. - * @access public - */ - function getAttachments() { - return $this->requestAttachments; - } - - /** - * gets the HTTP body for the current response. - * - * @param string $soapmsg The SOAP payload - * @return string The HTTP body, which includes the SOAP payload - * @access private - */ - function getHTTPBody($soapmsg) { - if (count($this->responseAttachments) > 0) { - $params['content_type'] = 'multipart/related; type="text/xml"'; - $mimeMessage = new Mail_mimePart('', $params); - unset($params); - - $params['content_type'] = 'text/xml'; - $params['encoding'] = '8bit'; - $params['charset'] = $this->soap_defencoding; - $mimeMessage->addSubpart($soapmsg, $params); - - foreach ($this->responseAttachments as $att) { - unset($params); - - $params['content_type'] = $att['contenttype']; - $params['encoding'] = 'base64'; - $params['disposition'] = 'attachment'; - $params['dfilename'] = $att['filename']; - $params['cid'] = $att['cid']; - - if ($att['data'] == '' && $att['filename'] <> '') { - if ($fd = fopen($att['filename'], 'rb')) { - $data = fread($fd, filesize($att['filename'])); - fclose($fd); - } else { - $data = ''; - } - $mimeMessage->addSubpart($data, $params); - } else { - $mimeMessage->addSubpart($att['data'], $params); - } - } - - $output = $mimeMessage->encode(); - $mimeHeaders = $output['headers']; - - foreach ($mimeHeaders as $k => $v) { - $this->debug("MIME header $k: $v"); - if (strtolower($k) == 'content-type') { - // PHP header() seems to strip leading whitespace starting - // the second line, so force everything to one line - $this->mimeContentType = str_replace("\r\n", " ", $v); - } - } - - return $output['body']; - } - - return parent::getHTTPBody($soapmsg); - } - - /** - * gets the HTTP content type for the current response. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type for the current response. - * @access private - */ - function getHTTPContentType() { - if (count($this->responseAttachments) > 0) { - return $this->mimeContentType; - } - return parent::getHTTPContentType(); - } - - /** - * gets the HTTP content type charset for the current response. - * returns false for non-text content types. - * - * Note: getHTTPBody must be called before this. - * - * @return string the HTTP content type charset for the current response. - * @access private - */ - function getHTTPContentTypeCharset() { - if (count($this->responseAttachments) > 0) { - return false; - } - return parent::getHTTPContentTypeCharset(); - } - - /** - * processes SOAP message received from client - * - * @param array $headers The HTTP headers - * @param string $data unprocessed request data from client - * @return mixed value of the message, decoded into a PHP type - * @access private - */ - function parseRequest($headers, $data) { - $this->debug('Entering parseRequest() for payload of length ' . strlen($data) . ' and type of ' . $headers['content-type']); - $this->requestAttachments = array(); - if (strstr($headers['content-type'], 'multipart/related')) { - $this->debug('Decode multipart/related'); - $input = ''; - foreach ($headers as $k => $v) { - $input .= "$k: $v\r\n"; - } - $params['input'] = $input . "\r\n" . $data; - $params['include_bodies'] = true; - $params['decode_bodies'] = true; - $params['decode_headers'] = true; - - $structure = Mail_mimeDecode::decode($params); - - foreach ($structure->parts as $part) { - if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) { - $this->debug('Have root part of type ' . $part->headers['content-type']); - $return = parent::parseRequest($part->headers, $part->body); - } else { - $this->debug('Have an attachment of type ' . $part->headers['content-type']); - $info['data'] = $part->body; - $info['filename'] = isset($part->d_parameters['filename']) ? $part->d_parameters['filename'] : ''; - $info['contenttype'] = $part->headers['content-type']; - $info['cid'] = $part->headers['content-id']; - $this->requestAttachments[] = $info; - } - } - - if (isset($return)) { - return $return; - } - - $this->setError('No root part found in multipart/related content'); - return; - } - $this->debug('Not multipart/related'); - return parent::parseRequest($headers, $data); - } -} - -/* - * For backwards compatiblity - */ -class nusoapservermime extends nusoap_server_mime { -} - -?> diff --git a/public/assets/css/print.css b/public/assets/css/print.css index 01e35378c..0c88f0cfb 100644 --- a/public/assets/css/print.css +++ b/public/assets/css/print.css @@ -15,8 +15,16 @@ html { } body { - font-family: "Dejavu Sans", dejavusans; - font-size:13px; + font-family: "Open Sans", "Dejavu Sans", dejavusans; + font-size:11pt; height:100%; margin-top: 20pt; +} + +.center { + text-align: center; +} + +.bold { + font-weight: bold; } \ No newline at end of file diff --git a/public/assets/css/thetool.css b/public/assets/css/thetool.css index 3722094ce..341894cbd 100644 --- a/public/assets/css/thetool.css +++ b/public/assets/css/thetool.css @@ -80,6 +80,30 @@ h1, h2, h3, h4, h5, h6 { color: #0d6efd; } +.contract-link { + +} + +.canceled { + text-decoration: line-through; +} + +/* tinymce */ +.tox-editor-header, +.tox-menubar, +.tox-toolbar-overlord, +.tox-toolbar__primary +{ + background: none; + background-color: #eee !important; +} + +/* allow icons in custom-file label */ +.custom-file-label::before { + font-family: "Font Awesome 6 Pro"; + content: "\f56f"; + padding-right: 6px; +} /************************** * custom styles @@ -220,6 +244,14 @@ h1, h2, h3, h4, h5, h6 { } +.color-shadow-b { + text-shadow: 1px 1px 2px black; +} +.color-shadow-2 { + text-shadow: 1px 1px 2px white; +} + + .pagination a { color: #007bff; } @@ -373,6 +405,231 @@ td.controls { border-color: #FF0088; } +.btn-outline-natur { + color: #000000; + background-color: #FFFFCC; +} + +.btn-outline-Rot-Gelb { + color: #FFFFFF; + border-left-color: #FF0000; + border-top-color: #FF0000; + border-right-color: #FFFF00; + border-bottom-color: #FFFF00; + background: linear-gradient(90deg, rgba(255,0,0,.5) 0%, rgba(255,0,0,.5) 50%, rgba(255,255,0,.5) 50%, rgba(255,255,0,.5) 100%); +} + +.btn-outline-Rot-Gruen { + color: #FFFFFF; + border-left-color: #FF0000; + border-top-color: #FF0000; + border-right-color: #00FF00; + border-bottom-color: #00FF00; + background: linear-gradient(90deg, rgba(255,0,0,.5) 0%, rgba(255,0,0,.5) 50%, rgba(0,255,0,.5) 50%, rgba(0,255,0,.5) 100%); +} + +.btn-outline-Rot-Blau { + color: #FFFFFF; + border-left-color: #FF0000; + border-top-color: #FF0000; + border-right-color: #0000FF; + border-bottom-color: #0000FF; + background: linear-gradient(90deg, rgba(255,0,0,.5) 0%, rgba(255,0,0,.5) 50%, rgba(0,0,255,.5) 50%, rgba(0,0,255,.5) 100%); +} + +.btn-outline-Rot-Violett { + color: #FFFFFF; + border-left-color: #FF0000; + border-top-color: #FF0000; + border-right-color: #8800FF; + border-bottom-color: #8800FF; + background: linear-gradient(90deg, rgba(255,0,0,.5) 0%, rgba(255,0,0,.5) 50%, rgba(136,0,255,.5) 50%, rgba(136,0,255,.5) 100%); +} + +.btn-outline-Rot-Grau { + color: #FFFFFF; + border-left-color: #FF0000; + border-top-color: #FF0000; + border-right-color: #888888; + border-bottom-color: #888888; + background: linear-gradient(90deg, rgba(255,0,0,.5) 0%, rgba(255,0,0,.5) 50%, rgba(136,136,136,.5) 50%, rgba(136,136,136,.5) 100%); +} + +.btn-outline-Gelb-Blau { + color: #000000; + border-left-color: #FFFF00; + border-top-color: #FFFF00; + border-right-color: #0000FF; + border-bottom-color: #0000FF; + background: linear-gradient(90deg, rgba(255,255,0,.5) 0%, rgba(255,255,0,.5) 50%, rgba(0,0,255,.5) 50%, rgba(0,0,255,.5) 100%); +} + +.btn-outline-Gelb-Violett { + color: #000000; + border-left-color: #FFFF00; + border-top-color: #FFFF00; + border-right-color: #8800FF; + border-bottom-color: #8800FF; + background: linear-gradient(90deg, rgba(255,255,0,.5) 0%, rgba(255,255,0,.5) 50%, rgba(136,0,255,.5) 50%, rgba(136,0,255,.5) 100%); +} + +.btn-outline-Gelb-Grau { + color: #000000; + border-left-color: #FFFF00; + border-top-color: #FFFF00; + border-right-color: #888888; + border-bottom-color: #888888; + background: linear-gradient(90deg, rgba(255,255,0,.5) 0%, rgba(255,255,0,.5) 50%, rgba(136,136,136,.5) 50%, rgba(136,136,136,.5) 100%); +} + +.btn-outline-Gruen-Blau { + color: #000000; + border-left-color: #00FF00; + border-top-color: #00FF00; + border-right-color: #0000FF; + border-bottom-color: #0000FF; + background: linear-gradient(90deg, rgba(0,255,0,.5) 0%, rgba(0,255,0,.5) 50%, rgba(0,0,255,.5) 50%, rgba(0,0,255,.5) 100%); +} + +.btn-outline-Gruen-Violett { + color: #000000; + border-left-color: #00FF00; + border-top-color: #00FF00; + border-right-color: #8800FF; + border-bottom-color: #8800FF; + background: linear-gradient(90deg, rgba(0,255,0,.5) 0%, rgba(0,255,0,.5) 50%, rgba(136,0,255,.5) 50%, rgba(136,0,255,.5) 100%); +} + +.btn-outline-Gruen-Grau { + color: #000000; + border-left-color: #00FF00; + border-top-color: #00FF00; + border-right-color: #888888; + border-bottom-color: #888888; + background: linear-gradient(90deg, rgba(0,255,0,.5) 0%, rgba(0,255,0,.5) 50%, rgba(136,136,136,.5) 50%, rgba(136,136,136,.5) 100%); +} + +.btn-outline-Braun-Blau { + color: #FFFFFF; + border-left-color: #A52A2A; + border-top-color: #A52A2A; + border-right-color: #0000FF; + border-bottom-color: #0000FF; + background: linear-gradient(90deg, rgba(165,42,42,.5) 0%, rgba(165,42,42,.5) 50%, rgba(0,0,255,.5) 50%, rgba(0,0,255,.5) 100%); +} + +.btn-outline-Braun-Violett { + color: #FFFFFF; + border-left-color: #A52A2A; + border-top-color: #A52A2A; + border-right-color: #8800FF; + border-bottom-color: #8800FF; + background: linear-gradient(90deg, rgba(165,42,42,.5) 0%, rgba(165,42,42,.5) 50%, rgba(136,0,255,.5) 50%, rgba(136,0,255,.5) 100%); +} + +.btn-outline-Braun-Grau { + color: #FFFFFF; + border-left-color: #A52A2A; + border-top-color: #A52A2A; + border-right-color: #888888; + border-bottom-color: #888888; + background: linear-gradient(90deg, rgba(165,42,42,.5) 0%, rgba(165,42,42,.5) 50%, rgba(136,136,136,.5) 50%, rgba(136,136,136,.5) 100%); +} + +.btn-outline-Braun-Gruen { + color: #FFFFFF; + border-left-color: #A52A2A; + border-top-color: #A52A2A; + border-right-color: #00FF00; + border-bottom-color: #00FF00; + background: linear-gradient(90deg, rgba(165,42,42,.5) 0%, rgba(165,42,42,.5) 50%, rgba(0,255,0,.5) 50%, rgba(0,255,0,.5) 100%); +} + +.btn-outline-Braun-Gelb { + color: #FFFFFF; + border-left-color: #A52A2A; + border-top-color: #A52A2A; + border-right-color: #FFFF00; + border-bottom-color: #FFFF00; + background: linear-gradient(90deg, rgba(165,42,42,.5) 0%, rgba(165,42,42,.5) 50%, rgba(255,255,0,.5) 50%, rgba(255,255,0,.5) 100%); +} + +.btn-outline-Braun-Rot { + color: #FFFFFF; + border-left-color: #A52A2A; + border-top-color: #A52A2A; + border-right-color: #FF0000; + border-bottom-color: #FF0000; + background: linear-gradient(90deg, rgba(165,42,42,.5) 0%, rgba(165,42,42,.5) 50%, rgba(255,0,0,.5) 50%, rgba(255,0,0,.5) 100%); +} + +.btn-outline-Schwarz-Rot { + color: #FFFFFF; + border-left-color: #000000; + border-top-color: #000000; + border-right-color: #FF0000; + border-bottom-color: #FF0000; + background: linear-gradient(90deg, rgba(0,0,0,.5) 0%, rgba(0,0,0,.5) 50%, rgba(255,0,0,.5) 50%, rgba(255,0,0,.5) 100%); +} + +.btn-outline-Schwarz-Gelb { + color: #FFFFFF; + border-left-color: #000000; + border-top-color: #000000; + border-right-color: #FFFF00; + border-bottom-color: #FFFF00; + background: linear-gradient(90deg, rgba(0,0,0,.5) 0%, rgba(0,0,0,.5) 50%, rgba(255,255,0,.5) 50%, rgba(255,255,0,.5) 100%); +} + +.btn-outline-Schwarz-Gruen { + color: #FFFFFF; + border-left-color: #000000; + border-top-color: #000000; + border-right-color: #00FF00; + border-bottom-color: #00FF00; + background: linear-gradient(90deg, rgba(0,0,0,.5) 0%, rgba(0,0,0,.5) 50%, rgba(0,255,0,.5) 50%, rgba(0,255,0,.5) 100%); +} + +.btn-outline-Schwarz-Blau { + color: #FFFFFF; + border-left-color: #000000; + border-top-color: #000000; + border-right-color: #0000FF; + border-bottom-color: #0000FF; + background: linear-gradient(90deg, rgba(0,0,0,.5) 0%, rgba(0,0,0,.5) 50%, rgba(0,0,255,.5) 50%, rgba(0,0,255,.5) 100%); +} + +.btn-outline-Schwarz-Violett { + color: #FFFFFF; + border-left-color: #000000; + border-top-color: #000000; + border-right-color: #8800FF; + border-bottom-color: #8800FF; + background: linear-gradient(90deg, rgba(0,0,0,.5) 0%, rgba(0,0,0,.5) 50%, rgba(136,0,255,.5) 50%, rgba(136,0,255,.5) 100%); +} + +.btn-outline-Schwarz-Grau { + color: #FFFFFF; + border-left-color: #000000; + border-top-color: #000000; + border-right-color: #888888; + border-bottom-color: #888888; + background: linear-gradient(90deg, rgba(0,0,0,.5) 0%, rgba(0,0,0,.5) 50%, rgba(136,136,136,.5) 50%, rgba(136,136,136,.5) 100%); +} + +.btn-outline-Schwarz-Braun { + color: #FFFFFF; + border-left-color: #000000; + border-top-color: #000000; + border-right-color: #A52A2A; + border-bottom-color: #A52A2A; + background: linear-gradient(90deg, rgba(0,0,0,.5) 0%, rgba(0,0,0,.5) 50%, rgba(165,42,42,.5) 50%, rgba(165,42,42,.5) 100%); +} + + + + + .text-white { color: #f00; diff --git a/public/assets/css/tinymce.css b/public/assets/css/tinymce.css new file mode 100644 index 000000000..55f940cb2 --- /dev/null +++ b/public/assets/css/tinymce.css @@ -0,0 +1,4 @@ +body { + font-family: Arial; + font-size: 12pt; +} \ No newline at end of file diff --git a/public/assets/images/the-tool-test-logo-top.png b/public/assets/images/the-tool-test-logo-top.png new file mode 100644 index 000000000..b4e8c5843 Binary files /dev/null and b/public/assets/images/the-tool-test-logo-top.png differ diff --git a/public/assets/images/the-tool-test-logo.png b/public/assets/images/the-tool-test-logo.png new file mode 100644 index 000000000..28e7d022c Binary files /dev/null and b/public/assets/images/the-tool-test-logo.png differ diff --git a/public/assets/js/leaflet.MakiMarkers.js b/public/assets/js/leaflet.MakiMarkers.js new file mode 100644 index 000000000..3227e56c7 --- /dev/null +++ b/public/assets/js/leaflet.MakiMarkers.js @@ -0,0 +1,103 @@ +/* + * Leaflet plugin to create map icons using Maki Icons from MapBox. + * + * References: + * Maki Icons: https://www.mapbox.com/maki/ + * Mapbox Marker API: https://www.mapbox.com/api-documentation/#retrieve-a-standalone-marker + * Possible icon names: https://raw.githubusercontent.com/mapbox/maki/master/layouts/all.json + * + * Usage: + * L.MakiMarkers.accessToken = ""; + * var icon = L.MakiMarkers.icon({icon: "rocket", color: "#b0b", size: "m"}); + * + * License: + * MIT: http://jseppi.mit-license.org/ + */ + /*global L:false */ +(function () { + "use strict"; + L.MakiMarkers = { + accessToken: null, + defaultColor: "#0a0", + defaultIcon: "circle-stroked", + defaultSize: "m", + apiUrl: "https://api.mapbox.com/v4/marker/", + smallOptions: { + iconSize: [20, 50], + popupAnchor: [0,-20] + }, + mediumOptions: { + iconSize: [30,70], + popupAnchor: [0,-30] + }, + largeOptions: { + iconSize: [36,90], + popupAnchor: [0,-40] + } + }; + + L.MakiMarkers.Icon = L.Icon.extend({ + options: { + //Mapbox API access token, see https://www.mapbox.com/api-documentation/?language=CLI#access-tokens + //Instead of setting with each icon, you can set globally as L.MakiMarkers.accessToken + accessToken: null, + //Maki icon: any valid name, see https://raw.githubusercontent.com/mapbox/maki/master/layouts/all.json + icon: L.MakiMarkers.defaultIcon, + //Marker color: short or long form hex color code + color: L.MakiMarkers.defaultColor, + //Marker size: "s" (small), "m" (medium), or "l" (large) + size: L.MakiMarkers.defaultSize, + shadowAnchor: null, + shadowSize: null, + shadowUrl: null, + className: "maki-marker" + }, + + initialize: function(options) { + var pin; + var tokenQuery; + + var accessToken = options.accessToken || L.MakiMarkers.accessToken; + if (!accessToken) { + throw new Error("Access to the Mapbox API requires a valid access token."); + } + + tokenQuery = "?access_token=" + accessToken; + options = L.setOptions(this, options); + + switch (options.size) { + case "s": + L.extend(options, L.MakiMarkers.smallOptions); + break; + case "l": + L.extend(options, L.MakiMarkers.largeOptions); + break; + default: + options.size = "m"; + L.extend(options, L.MakiMarkers.mediumOptions); + break; + } + + pin = "pin-" + options.size; + + if (options.icon !== null) { + pin += "-" + options.icon; + } + + if (options.color !== null) { + if (options.color.charAt(0) === "#") { + options.color = options.color.substr(1); + } + + pin += "+" + options.color; + } + + options.iconUrl = "" + L.MakiMarkers.apiUrl + pin + ".png" + tokenQuery; + options.iconRetinaUrl = L.MakiMarkers.apiUrl + pin + "@2x.png" + tokenQuery; + } + }); + + L.MakiMarkers.icon = function(options) { + return new L.MakiMarkers.Icon(options); + }; +})(); diff --git a/public/assets/pdf/.gitignore b/public/assets/pdf/.gitignore new file mode 100644 index 000000000..bf7d0f2f3 --- /dev/null +++ b/public/assets/pdf/.gitignore @@ -0,0 +1 @@ +logo-address-*.png diff --git a/public/assets/pdf/logo-andom.png b/public/assets/pdf/logo-andom.png new file mode 100644 index 000000000..e084e65fb Binary files /dev/null and b/public/assets/pdf/logo-andom.png differ diff --git a/public/assets/pdf/logo-bbaustria.png b/public/assets/pdf/logo-bbaustria.png new file mode 100644 index 000000000..91be7713d Binary files /dev/null and b/public/assets/pdf/logo-bbaustria.png differ diff --git a/public/assets/pdf/logo-sknetworx.png b/public/assets/pdf/logo-sknetworx.png new file mode 100644 index 000000000..0fed8b529 Binary files /dev/null and b/public/assets/pdf/logo-sknetworx.png differ diff --git a/public/assets/pdf/logo.png b/public/assets/pdf/logo-xinon.png similarity index 100% rename from public/assets/pdf/logo.png rename to public/assets/pdf/logo-xinon.png diff --git a/public/docs/preorder-api.yaml b/public/docs/preorder-api.yaml index 29061c018..2ff087c01 100644 --- a/public/docs/preorder-api.yaml +++ b/public/docs/preorder-api.yaml @@ -1,7 +1,7 @@ openapi: 3.0.1 info: title: thetool Preorder API - description: API Dokumentation für thetool Vorbestellung + description: API Dokumentation für thetool Akquise-Plattform license: name: Apache 2.0 License url: http://www.apache.org/licenses/LICENSE-2.0.html @@ -15,19 +15,145 @@ tags: - name: preorder description: Informationen zum Netzgebiet und Speichern von Vorbestellungen paths: + /addressdb/getClusters: + get: + tags: + - addressdb + summary: Gibt alle Cluster aus + description: Retourniert Liste aller Cluster mit ID und Name + operationId: getClusters + responses: + '200': + description: Successful operation + content: + "application/json": + schema: + type: object + properties: + status: + type: string + description: Status string + example: OK + result: + type: object + properties: + clusters: + type: array + items: + type: object + properties: + id: + type: string + description: ID des Clusters + example: "JP-TYO-01-4" + name: + type: string + description: Name des Clusters + example: "Tokyo - Akihabara Süd" + '400': + description: | + Bad Request + + Parameter missing or malformed + '401': + description: Unauthorized + /addressdb/searchAddress: + get: + tags: + - addressdb + summary: Freitextsuche nach Adressen mit Ausbaustatus + description: Sucht Adressen die den Suchbegriff beinhalten. Retourniert Adressen mit Ausbaustatus und Wohneinheiten + operationId: searchAddresses + parameters: + - name: format + description: "Ausgabeformat: `flat` (Ein Array-Element pro Wohneinheit mit Gebäudedaten; **default**) oder `tree` (Ein Array-Element pro Gebäude mit Wohneinheiten-Array)" + in: query + schema: + type: string + example: flat + - name: search + description: Suchbegriff + in: query + schema: + type: string + required: true + responses: + '200': + description: | + Successful operation + + Der Rückgabewert `preorderType` gibt an, welche Vorbestelltypen an dieser Adresse erlaubt sind: + + | preorderType | description | + |--------------|-------------| + | interest | Interessensbekundung | + | provision | Vorsorgeanschluss | + | order | Vollanschluss | + | reorder | Nachbestellung (nach Bauabschluss) | + + Ein leeres Array bedeutet, dass derzeit kein Ausbau stattfindet/geplant ist. + + --- + + Ist bekannt, dass die Adresse zukünftig ausgebaut wird, steht im Feld `rollout_year` das geplante Ausbaujahr. `rollout_info` kann weitere informationen beinhalten. + content: + "application/json (format: tree)": + schema: + type: object + properties: + status: + type: string + description: Status string + example: OK + result: + type: object + properties: + addresses: + $ref: '#/components/schemas/AddressesTree' + "application/json (format: flat)": + schema: + type: object + properties: + status: + type: string + description: Status string + example: OK + result: + type: object + properties: + addresses: + $ref: '#/components/schemas/Addresses' + '400': + description: | + Bad Request + + Parameter missing or malformed + '401': + description: Unauthorized /addressdb/findAddress: get: tags: - addressdb - summary: Adressen suchen - description: Sucht nach Adressen. Retourniert Adressen mit Wohneinheiten + summary: Strukturierte Suche nach Adressen mit Ausbaustatus + description: Sucht nach Adressen. Retourniert Adressen mit Ausbaustatus und Wohneinheiten operationId: findAddresses parameters: + - name: format + description: "Ausgabeformat: `flat` (Ein Array-Element pro Wohneinheit mit Gebäudedaten; **default**) oder `tree` (Ein Array-Element pro Gebäude mit Wohneinheiten-Array)" + in: query + schema: + type: string + - name: cluster_id + description: Cluster ID + in: query + schema: + type: string - name: street description: Straße Suchbegriff in: query schema: type: string + required: true - name: zip description: Postleitzahl Suchbegriff in: query @@ -38,6 +164,11 @@ paths: in: query schema: type: string + - name: district + description: Ortsteil Suchbegriff + in: query + schema: + type: string - name: housenumber description: Hausnummer Suchbegriff in: query @@ -56,8 +187,27 @@ paths: | provision | Vorsorgeanschluss | | order | Vollanschluss | | reorder | Nachbestellung (nach Bauabschluss) | + + Ein leeres Array bedeutet, dass derzeit kein Ausbau stattfindet/geplant ist. + + --- + + Ist bekannt, dass die Adresse zukünftig ausgebaut wird, steht im Feld `rollout_year` das geplante Ausbaujahr. `rollout_info` kann weitere informationen beinhalten. content: - application/json: + "application/json (format: tree)": + schema: + type: object + properties: + status: + type: string + description: Status string + example: OK + result: + type: object + properties: + addresses: + $ref: '#/components/schemas/AddressesTree' + "application/json (format: flat)": schema: type: object properties: @@ -85,6 +235,11 @@ paths: description: Sucht nach Straßen operationId: findStreets parameters: + - name: cluster_id + description: Cluster ID + in: query + schema: + type: string - name: street description: Straße Suchbegriff in: query @@ -132,6 +287,11 @@ paths: description: Sucht nach Postleitzahlen operationId: findZips parameters: + - name: cluster_id + description: Cluster ID + in: query + schema: + type: string - name: zip description: Postleitzahl Suchbegriff in: query @@ -169,6 +329,11 @@ paths: description: Sucht nach Gemeinden operationId: findCity parameters: + - name: cluster_id + description: Cluster ID + in: query + schema: + type: string - name: zip description: Postleitzahl Suchbegriff in: query @@ -203,18 +368,74 @@ paths: Parameter missing or malformed '401': description: Unauthorized + /addressdb/findDistrict: + get: + tags: + - addressdb + summary: Ortsteile suchen + description: Sucht nach Ortsteilen + operationId: findDistrict + parameters: + - name: cluster_id + description: Cluster ID + in: query + schema: + type: string + - name: zip + description: Postleitzahl Suchbegriff + in: query + schema: + type: string + - name: city + description: Gemeinde Suchbegriff + in: query + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + properties: + status: + type: string + description: Status string + example: OK + result: + type: object + properties: + cities: + $ref: '#/components/schemas/CityDistricts' + '400': + description: | + Bad Request + + Parameter missing or malformed + '401': + description: Unauthorized /preorder: post: tags: - preorder - summary: Vorbestellung registrieren + summary: (Vor-)bestellung registrieren description: | - Registriert eine Vorbestellung. + Registriert eine (Vor-)bestellung. Bestellungsart wird mit `preorderType` definiert. + + Handelt es sich um einen zusätzlichen Anschluss in der Wohneinheit muss der Paramerter `isAdditionalOrder` auf `true` gestellt werden, da sonst ein Fehler zurückgegeben wird. --- - Parameter `address`: Anschlussadresse - Parameter `address_info`: **(Optional)** Zusätzliche Informationen zur Adresse + Parameter `address`: Anschlussadresse. + + Soll Starterkit an Anschlussadresse gesendet werden, muss `address.is_shipping` auf true gestellt werden, bei false wird das Starterkit an Vertragsinhaber (`customer`) gesendet. + + Wohneinheitsidentifikation (Block, Stiege, Stock, Tür) kann strukturiert mit jeweils einem eigenen Feld übergeben werden oder alle Wohneinheitsdaten in einem einzigen String (`unit_string`). + + --- + + Parameter `address_info`: **(Optional)** Zusätzliche Informationen zur Anschlusssdresse Parameter `customer`: Vertragsinhaber @@ -261,7 +482,6 @@ paths: --- - Parameter `additionalData`: **(Optional)** Object für zusätzliche individuelle Daten, die in der Vorbestellung gespeichert werden. Wird in `GET /preorder` retourniert. operationId: submitPreorder @@ -293,6 +513,19 @@ paths: code: type: string description: Code für Statusabfrage + example: A1B2C3D4 + additionalData: + type: object + description: Benutzerdefiniertes Objekt. Wird unverändert gespeichert und in `GET /preorder` wieder ausgegeben + example: + myData: Hallo + moreData: Welt + lotsMoreData: + - key: name + value: test + - key: another Key + value: more value + '400': description: | Bad Request @@ -300,56 +533,101 @@ paths: Parameter missing or malformed '401': description: Unauthorized + '403': + description: Vorbestellung für diese Wohneinheit bereits vorhanden '404': description: Adresse oder Wohneinheit nicht gefunden -# /preorder/{code}: -# get: -# tags: -# - preorder -# summary: Details zur Vorbestellung (noch nicht Final) -# description: Gibt Details zum Status der Vorbestellung/Bestellung zurück **(noch nicht Final)** -# operationId: getPreorderStatus -# parameters: -# - name: code -# in: path -# description: code der Vorbestellung -# required: true -# schema: -# type: string -# responses: -# '200': -# description: | -# Successful operation -# -# Mögliche Werte für Rückgabewert `status` -# -# | id | text | description | -# |------|------|-------------| -# | 100 | Aufgenommen | Interessensbekundung/Vorbestellung aufgenommen | -# | 110 | Tiefbau in Planung | | -# | 120 | Tiefbau in Arbeit | | -# | 200 | Tiefbau abgeschlossen | | -# | 210 | Leitungsbau in planung | | -# | 220 | Leitungsbau in Arbeit | | -# | 230 | Leitungsbau abgeschlossen | | -# | 300 | Leitungskonfiguration in Planung | | -# | 310 | Leitungskonfiguration in Arbeit | | -# | 320 | Leitung hergestellt | Produkt bestellbar | -# content: -# application/json: -# schema: -# type: object -# properties: -# status: -# type: string -# description: Status string -# example: OK -# result: -# $ref: '#/components/schemas/preorderStatusDetail' -# '401': -# description: Unauthorized -# '404': -# description: Vorbestellung nicht gefunden + /preorder/{code}: + get: + tags: + - preorder + summary: Details und Status zur Vorbestellung + description: Gibt Details zum Status der Vorbestellung/Bestellung zurück + operationId: getPreorderStatus + parameters: + - name: code + in: path + description: code der Vorbestellung oder OAID der Wohneinheit + required: true + schema: + type: string + responses: + '200': + description: | + Successful operation + + Mögliche Werte für Rückgabewert `status`: + + | code | text | description | + |------|------|-------------| + | 10 | new | Neu | + | 110 | Underground construction planning | Tiefbau in Planung | + | 120 | Underground construction planning finished | Tiefbau Planung abgeschlossen | + | 130 | Underground construction work assigned | Bauauftrag zugeteilt | + | 140 | Conduit at property border | Rohr an Grundstücksgrenze | + | 200 | Conduit in building | Rohr im Gebäude | + | 210 | Fiber planning | Leitungsplan in Arbeit | + | 220 | Fiber planning finished | Leitungsplan abgeschlossen | + | 230 | Fiber installation work assigned | Bauauftrag zugeteilt | + | 240 | Fiber in building | Faser im Gebäude | + | 250 | ONT ready | ONT vorbereitet | + | 260 | ONT picked up or shipped | ONT abgeholt oder versandt | + | 300 | ONT installed | ONT in Betrieb | + | 500 | Finished | Fertiggestellt | + | 899 | Cancelled | Storniert/Gekündigt | + content: + application/json: + schema: + type: object + properties: + status: + type: string + description: Status string + example: OK + result: + $ref: '#/components/schemas/preorderStatusDetail' + '401': + description: Unauthorized + '404': + description: Vorbestellung nicht gefunden + delete: + tags: + - preorder + summary: Bestellung stornieren/kündigen + description: Erstellt einen Storno Request + operationId: cancelPreorder + parameters: + - name: code + in: path + description: code der Vorbestellung oder OAID der Wohneinheit + required: true + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: object + properties: + status: + type: string + description: Status string + example: OK + result: + type: object + properties: + message: + type: string + description: Statustext + example: Cancellation request submited + '401': + description: Unauthorized + '403': + description: Keine Berechtigung oder Storno Request bereits vorhanden + '404': + description: Bestellung nicht gefunden oder bereits storniert components: schemas: Zips: @@ -360,17 +638,37 @@ components: type: array items: type: string + CityDistricts: + type: object + additionalProperties: + type: array + items: + type: string + example: + Premstätten: + - Hautzendorf + - Laa + - Oberpremstätten + - Unterpremstätten Streets: type: array items: type: string + AddressesTree: + type: array + items: + $ref: '#/components/schemas/AddressTree' Addresses: type: array items: $ref: '#/components/schemas/Address' - Address: + AddressTree: type: object properties: + oaid: + type: string + description: OAID des Gebäudes + example: AT-9999-abcdef01 street: type: string description: Strasse @@ -385,8 +683,136 @@ components: example: 9999 city: type: string - description: Ort - example: Beispielhausen + description: Ortschaft + example: Ortschaft + municipality: + type: string + description: Gemeinde + example: Gemeinde + district: + type: string + description: Ortsteil + example: Ortsteil + lot_number: + type: string + description: Grundstücksnummer + example: 123/7 + building_unit_count: + type: int64 + description: Anzahl Wohneinheiten im Gebäude + example: 6 + gps_lat: + typee: float + description: Breitengrad der GPS-Koordinate (Dezimal) + example: 48.517560 + gps_long: + typee: float + description: Längengrad der GPS-Koordinate (Dezimal) + example: 13.950665 + rollout_year: + type: integer + description: Jahr des geplanten Ausbaus + example: 2024 + rollout_info: + type: string + description: Infotext begzl. Bauplanung + example: null + preorderTypes: + type: array + example: ["interest", "provision", "order", "reorder"] + description: | + Erlaubte Vorbestelltypen: + + | preorderType | description | + |--------------|-------------| + | interest | Interessensbekundung | + | provision | Vorsorgeanschluss | + | order | Vollanschluss | + | reorder | Nachbestellung (nach Bauabschluss) | + items: + type: string + units: + type: array + items: + type: object + properties: + oaid: + type: string + description: OAID der Wohneinheit + example: AT-9999-abcdef01.001 + num: + type: int64 + description: Fortlaufende Nummer der Wohneinheit + example: 2 + block: + type: string + description: Block + example: "" + stock: + type: string + description: Stock + example: 42 + stiege: + type: string + description: Stiege + example: "" + tuer: + type: string + description: Tür + example: 1337 + zusatz: + type: string + description: Addresszusatz + example: im Carport + required: + - street + Address: + type: object + properties: + oaid: + type: string + description: OAID der Wohneinheit + example: AT-9999-abcdef01.001 + building_oaid: + type: string + description: OAID des Gebäudes + example: AT-9999-abcdef01 + street: + type: string + description: Strasse + example: Beispielstraße + housenumber: + type: string + description: Hausnummer + example: 13 + zip: + type: string + description: PLZ + example: 9999 + city: + type: string + description: Ortschaft + example: Ortschaft + municipality: + type: string + description: Gemeinde + example: Gemeinde + district: + type: string + description: Ortsteil + example: Ortsteil + lot_number: + type: string + description: Grundstücksnummer + example: 123/7 + building_unit_count: + type: int64 + description: Anzahl Wohneinheiten im Gebäude + example: 6 + num: + type: int64 + description: Fortlaufende Nummer der Wohneinheit + example: 2 block: type: string description: Block @@ -403,6 +829,10 @@ components: type: string description: Tür example: 1337 + zusatz: + type: string + description: Addresszusatz + example: im Carport gps_lat: typee: float description: Breitengrad der GPS-Koordinate (Dezimal) @@ -415,6 +845,10 @@ components: type: integer description: Jahr des geplanten Ausbaus example: 2024 + rollout_info: + type: string + description: Infotext begzl. Bauplanung + example: Bauplan 2024 preorderTypes: type: array example: ["interest", "provision", "order", "reorder"] @@ -434,6 +868,9 @@ components: addressResponse: type: object properties: + cluster_id: + type: string + description: Cluster ID street: type: string description: Strasse der Anschlussadresse @@ -446,6 +883,9 @@ components: city: type: string description: Ort der Anschlussadresse + municipality: + type: string + description: Gemeinde der Anschlussadresse block: type: string description: Block der Anschlussadresse @@ -476,12 +916,31 @@ components: street: type: string description: Straße Kunde + housenumber: + type: string + description: Hausnummer Kunde zip: type: string description: PLZ Kunde city: type: string description: Ort Kunde + block: + type: string + description: Adresszusatz + example: null + stiege: + type: string + description: Adresszusatz + example: null + stock: + type: string + description: Adresszusatz + example: null + tuer: + type: string + description: Adresszusatz + example: null phone: type: string description: Telefonnummer Kunde @@ -491,6 +950,18 @@ components: preorderRequest: type: object properties: + preorderType: + type: string + enum: [interest, provision, order] + description: | + Vorbestelltyp + + | preorderType | Description | + |--------------|-------------| + | interest | Interessensbekundung | + | provision | Vorsorgeanschluss | + | order | Vollanschluss | + | reorder | Nachbestellung (nach Bauabschluss) | connectionType: type: string enum: [single-dwelling, multi-dwelling, apartment-building, apartment, business] @@ -505,20 +976,24 @@ components: connectionCount: type: integer default: 1 - description: Anzahl Anschlüsse für Rabatt bei mehreren Anschlüssen in Mehrfamilienhaus + description: Anzahl Anschlüsse bei mehreren Anschlüssen in Mehrfamilienhaus nullable: true - preorderType: + isAdditionalOrder: + type: bolean + default: false + description: wenn es sich um eine Zweitbestellung auf einer Wohneinheit handelt, muss `isAdditonalOrder` auf `true` gestellt werden, damit die Bestellung akzeptiert wird. + nullable: true + technology: type: string - enum: [interest, provision, order] - description: | - Vorbestelltyp - - | preorderType | Description | - |--------------|-------------| - | interest | Interessensbekundung| - | provision | Vorsorgeanschluss| - | order | Vollanschluss| - | reorder | Nachbestellung (nach Bauabschluss) | + default: gpon + description: Bei Provider eingesetzte Technologie (optional, falls für Patchpunkt im POP nötig) + example: gpon + nullable: true + patchposition: + type: string + default: null + description: Patchpunkt im POP (optional) + nullable: true acceptMarketing: type: boolean description: Zustimmung Datenspeicherung/-weitergabe @@ -567,6 +1042,14 @@ components: type: string description: Tür der Anschlussadresse example: 1337 + unit_string: + type: string + description: Zusatzangaben zur Identifizierung der Wohneinheit in einem String. Kann statt den Einzelfeldern (Block, Stiege, Stock, Tür) angegeben werden + example: Stg. 2 Stock 3 Tür 7 + is_shipping: + type: boolean + description: Soll Starterkit an Anschlussadresse gesendet werden. Bei false wird das Starterkit an Vertrasinhaber (`customer`) gesendet. + example: true required: - street - housenumber @@ -608,8 +1091,12 @@ components: example: Nachname street: type: string - description: Straße und Hausnummer Kunde - example: "Beispielstraße 42" + description: Straße Kunde + example: Beispielstraße + housenumber: + type: string + description: Hausnummer Kunde + example: 42 zip: type: string description: PLZ Kunde @@ -618,6 +1105,26 @@ components: type: string description: Ort Kunde example: Beispielhausen + block: + type: string + description: Adresszusatz + example: null + stiege: + type: string + description: Adresszusatz + example: null + stock: + type: string + description: Adresszusatz + example: null + tuer: + type: string + description: Adresszusatz + example: null + unit_string: + type: string + description: Zusatzangaben zur Identifizierung der Wohneinheit in einem String. Kann statt den Einzelfeldern (Block, Stiege, Stock, Tür) angegeben werden + example: Stg. 2 Stock 3 Tür 7 phone: type: string description: Telefonnummer Kunde @@ -688,21 +1195,117 @@ components: preorderStatusDetail: type: object properties: + code: + type: string + description: Eindeutiger Code der Vorbestellung + example: A1B2C3D4 + oaid: + type: string + description: Open Access ID der Wohneinheit + example: AT-9999-abcdef01.001 + status: + type: object + properties: + code: + type: integer + description: status ID + example: 230 + text: + type: string + description: Statustext + example: Fiber installation work assigned + connectionType: + type: string + enum: [single-dwelling, multi-dwelling, apartment-building, apartment, business] + description: | + |connectionType | description | + |---------------|-------------| + | single-dwelling | Einfamilienhaus + | multi-dwelling | Mehrfamilienhaus (bis 3 Wohneinheiten) + | apartment-building | Mehrparteienhaus (ab 4 Wohneinheiten) + | apartment | Wohneinheit in Mehrparteienhaus + | business | Gewerbebetrieb | + connectionCount: + type: integer + default: 1 + description: Anzahl Anschlüsse für Rabatt bei mehreren Anschlüssen in Mehrfamilienhaus + nullable: true + preorderType: + type: string + enum: [interest, provision, order] + description: | + Vorbestelltyp + + | preorderType | Description | + |--------------|-------------| + | interest | Interessensbekundung | + | provision | Vorsorgeanschluss | + | order | Vollanschluss | + | reorder | Nachbestellung (nach Bauabschluss) | + acceptMarketing: + type: boolean + description: Zustimmung Datenspeicherung/-weitergabe + acceptAgb: + type: boolean + description: Zustimmung AGB + acceptDsgvo: + type: boolean + description: Zustimmung DSGVO + acceptWithdrawal: + type: boolean + description: Informationen zu Rücktrittsrecht akzeptiert + address_info: + type: string + description: Zusätzliche Info zur Adresse + example: im Carport address: $ref: '#/components/schemas/addressResponse' customer: $ref: '#/components/schemas/customerResponse' - status: + addonServices: + type: array + description: | + + Zusätzlich gebuchte Services + + Services müssen nicht vordefiniert sein, es können benutzerdefinierte Services übergeben werden + items: + type: object + properties: + service: + type: string + description: Name des gebuchten Service + example: installation_inhouse + ordered: + type: boolean + description: Wurde dieses Service dazu gebucht + example: true + data: + type: array + items: + type: object + description: Zusätzlich benötigte Felder für Service + properties: + name: + type: string + description: Name für zusätzliches Feld + example: accept_data_forwarding + value: + type: string + description: Wert für zusätzliches Feld + example: true + additionalData: type: object - properties: - id: - type: integer - description: status ID - example: 220 - text: - type: string - description: Statustext - example: Tiefbau abgeschlossen, Leitungsbau ausständig + description: Benutzerdefiniertes Objekt. Wird unverändert gespeichert und in `GET /preorder` wieder ausgegeben + example: + myData: Hallo + moreData: Welt + lotsMoreData: + - key: name + value: test + - key: another Key + value: more value + securitySchemes: api_key_header: type: apiKey diff --git a/public/plugins/tinymce/icons/default/icons.min.js b/public/plugins/tinymce/icons/default/icons.min.js new file mode 100644 index 000000000..bd16eb72f --- /dev/null +++ b/public/plugins/tinymce/icons/default/icons.min.js @@ -0,0 +1 @@ +tinymce.IconManager.add("default",{icons:{"accessibility-check":'',"action-next":'',"action-prev":'',addtag:'',"align-center":'',"align-justify":'',"align-left":'',"align-none":'',"align-right":'',"arrow-left":'',"arrow-right":'',bold:'',bookmark:'',"border-style":'',"border-width":'',brightness:'',browse:'',cancel:'',"cell-background-color":'',"cell-border-color":'',"change-case":'',"character-count":'',"checklist-rtl":'',checklist:'',checkmark:'',"chevron-down":'',"chevron-left":'',"chevron-right":'',"chevron-up":'',close:'',"code-sample":'',"color-levels":'',"color-picker":'',"color-swatch-remove-color":'',"color-swatch":'',"comment-add":'',comment:'',contrast:'',copy:'',crop:'',"cut-column":'',"cut-row":'',cut:'',"document-properties":'',drag:'',"duplicate-column":'',"duplicate-row":'',duplicate:'',"edit-block":'',"edit-image":'',"embed-page":'',embed:'',emoji:'',export:'',fill:'',"flip-horizontally":'',"flip-vertically":'',footnote:'',"format-painter":'',format:'',fullscreen:'',gallery:'',gamma:'',help:'',"highlight-bg-color":'',home:'',"horizontal-rule":'',"image-options":'',image:'',indent:'',info:'',"insert-character":'',"insert-time":'',invert:'',italic:'',language:'',"line-height":'',line:'',link:'',"list-bull-circle":'',"list-bull-default":'',"list-bull-square":'',"list-num-default-rtl":'',"list-num-default":'',"list-num-lower-alpha-rtl":'',"list-num-lower-alpha":'',"list-num-lower-greek-rtl":'',"list-num-lower-greek":'',"list-num-lower-roman-rtl":'',"list-num-lower-roman":'',"list-num-upper-alpha-rtl":'',"list-num-upper-alpha":'',"list-num-upper-roman-rtl":'',"list-num-upper-roman":'',lock:'',ltr:'',"more-drawer":'',"new-document":'',"new-tab":'',"non-breaking":'',notice:'',"ordered-list-rtl":'',"ordered-list":'',orientation:'',outdent:'',"page-break":'',paragraph:'',"paste-column-after":'',"paste-column-before":'',"paste-row-after":'',"paste-row-before":'',"paste-text":'',paste:'',"permanent-pen":'',plus:'',preferences:'',preview:'',print:'',quote:'',redo:'',reload:'',"remove-formatting":'',remove:'',"resize-handle":'',resize:'',"restore-draft":'',"rotate-left":'',"rotate-right":'',rtl:'',save:'',search:'',"select-all":'',selected:'',settings:'',sharpen:'',sourcecode:'',"spell-check":'',"strike-through":'',subscript:'',superscript:'',"table-caption":'',"table-cell-classes":'',"table-cell-properties":'',"table-cell-select-all":'',"table-cell-select-inner":'',"table-classes":'',"table-delete-column":'',"table-delete-row":'',"table-delete-table":'',"table-insert-column-after":'',"table-insert-column-before":'',"table-insert-row-above":'',"table-insert-row-after":'',"table-left-header":'',"table-merge-cells":'',"table-row-numbering-rtl":'',"table-row-numbering":'',"table-row-properties":'',"table-split-cells":'',"table-top-header":'',table:'',template:'',"temporary-placeholder":'',"text-color":'',toc:'',translate:'',typography:'',underline:'',undo:'',unlink:'',unlock:'',"unordered-list":'',unselected:'',upload:'',user:'',"vertical-align":'',visualblocks:'',visualchars:'',warning:'',"zoom-in":'',"zoom-out":''}}); \ No newline at end of file diff --git a/public/plugins/tinymce/langs/README.md b/public/plugins/tinymce/langs/README.md new file mode 100644 index 000000000..a52bf03f9 --- /dev/null +++ b/public/plugins/tinymce/langs/README.md @@ -0,0 +1,3 @@ +This is where language files should be placed. + +Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/ diff --git a/public/plugins/tinymce/langs/de.js b/public/plugins/tinymce/langs/de.js new file mode 100644 index 000000000..319e45d48 --- /dev/null +++ b/public/plugins/tinymce/langs/de.js @@ -0,0 +1,412 @@ +/*! + * TinyMCE Language Pack + * + * Copyright (c) 2022 Ephox Corporation DBA Tiny Technologies, Inc. + * Licensed under the Tiny commercial license. See https://www.tiny.cloud/legal/ + */ +tinymce.addI18n('de', { +"Redo": "Wiederholen", +"Undo": "Rückgängig machen", +"Cut": "Ausschneiden", +"Copy": "Kopieren", +"Paste": "Einfügen", +"Select all": "Alles auswählen", +"New document": "Neues Dokument", +"Ok": "Ok", +"Cancel": "Abbrechen", +"Visual aids": "Visuelle Hilfen", +"Bold": "Fett", +"Italic": "Kursiv", +"Underline": "Unterstrichen", +"Strikethrough": "Durchgestrichen", +"Superscript": "Hochgestellt", +"Subscript": "Tiefgestellt", +"Clear formatting": "Formatierung entfernen", +"Remove": "Entfernen", +"Align left": "Linksbündig ausrichten", +"Align center": "Zentrieren", +"Align right": "Rechtsbündig ausrichten", +"No alignment": "Keine Ausrichtung", +"Justify": "Blocksatz", +"Bullet list": "Aufzählung", +"Numbered list": "Nummerierte Liste", +"Decrease indent": "Einzug verkleinern", +"Increase indent": "Einzug vergrößern", +"Close": "Schließen", +"Formats": "Formate", +"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.": "Ihr Browser unterstützt leider keinen direkten Zugriff auf die Zwischenablage. Bitte benutzen Sie die Tastenkombinationen Strg+X/C/V.", +"Headings": "Überschriften", +"Heading 1": "Überschrift 1", +"Heading 2": "Überschrift 2", +"Heading 3": "Überschrift 3", +"Heading 4": "Überschrift 4", +"Heading 5": "Überschrift 5", +"Heading 6": "Überschrift 6", +"Preformatted": "Vorformatiert", +"Div": "Div", +"Pre": "Pre", +"Code": "Code", +"Paragraph": "Absatz", +"Blockquote": "Blockzitat", +"Inline": "Zeichenformate", +"Blocks": "Blöcke", +"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Einfügen ist nun im unformatierten Textmodus. Inhalte werden ab jetzt als unformatierter Text eingefügt, bis Sie diese Einstellung wieder deaktivieren.", +"Fonts": "Schriftarten", +"Font sizes": "Schriftgrößen", +"Class": "Klasse", +"Browse for an image": "Bild...", +"OR": "ODER", +"Drop an image here": "Bild hier ablegen", +"Upload": "Hochladen", +"Uploading image": "Bild wird hochgeladen", +"Block": "Blocksatz", +"Align": "Ausrichtung", +"Default": "Standard", +"Circle": "Kreis", +"Disc": "Scheibe", +"Square": "Rechteck", +"Lower Alpha": "Lateinisches Alphabet in Kleinbuchstaben", +"Lower Greek": "Griechische Kleinbuchstaben", +"Lower Roman": "Kleiner römischer Buchstabe", +"Upper Alpha": "Lateinisches Alphabet in Großbuchstaben", +"Upper Roman": "Großer römischer Buchstabe", +"Anchor...": "Textmarke", +"Anchor": "Anker", +"Name": "Name", +"ID": "ID", +"ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "Die ID muss mit einem Buchstaben beginnen gefolgt von Buchstaben, Zahlen, Bindestrichen, Punkten, Doppelpunkten oder Unterstrichen.", +"You have unsaved changes are you sure you want to navigate away?": "Die Änderungen wurden noch nicht gespeichert. Sind Sie sicher, dass Sie diese Seite verlassen wollen?", +"Restore last draft": "Letzten Entwurf wiederherstellen", +"Special character...": "Sonderzeichen...", +"Special Character": "Sonderzeichen", +"Source code": "Quellcode", +"Insert/Edit code sample": "Codebeispiel einfügen/bearbeiten", +"Language": "Sprache", +"Code sample...": "Codebeispiel...", +"Left to right": "Von links nach rechts", +"Right to left": "Von rechts nach links", +"Title": "Titel", +"Fullscreen": "Vollbild", +"Action": "Aktion", +"Shortcut": "Tastenkombination", +"Help": "Hilfe", +"Address": "Adresse", +"Focus to menubar": "Fokus auf Menüleiste", +"Focus to toolbar": "Fokus auf Symbolleiste", +"Focus to element path": "Fokus auf Elementpfad", +"Focus to contextual toolbar": "Fokus auf kontextbezogene Symbolleiste", +"Insert link (if link plugin activated)": "Link einfügen (wenn Link-Plugin aktiviert ist)", +"Save (if save plugin activated)": "Speichern (wenn Save-Plugin aktiviert ist)", +"Find (if searchreplace plugin activated)": "Suchen (wenn Suchen/Ersetzen-Plugin aktiviert ist)", +"Plugins installed ({0}):": "Installierte Plugins ({0}):", +"Premium plugins:": "Premium-Plugins:", +"Learn more...": "Erfahren Sie mehr dazu...", +"You are using {0}": "Sie verwenden {0}", +"Plugins": "Plugins", +"Handy Shortcuts": "Praktische Tastenkombinationen", +"Horizontal line": "Horizontale Linie", +"Insert/edit image": "Bild einfügen/bearbeiten", +"Alternative description": "Alternative Beschreibung", +"Accessibility": "Barrierefreiheit", +"Image is decorative": "Bild ist dekorativ", +"Source": "Quelle", +"Dimensions": "Abmessungen", +"Constrain proportions": "Seitenverhältnis beibehalten", +"General": "Allgemein", +"Advanced": "Erweitert", +"Style": "Formatvorlage", +"Vertical space": "Vertikaler Raum", +"Horizontal space": "Horizontaler Raum", +"Border": "Rahmen", +"Insert image": "Bild einfügen", +"Image...": "Bild...", +"Image list": "Bildliste", +"Resize": "Skalieren", +"Insert date/time": "Datum/Uhrzeit einfügen", +"Date/time": "Datum/Uhrzeit", +"Insert/edit link": "Link einfügen/bearbeiten", +"Text to display": "Anzuzeigender Text", +"Url": "URL", +"Open link in...": "Link öffnen in...", +"Current window": "Aktuelles Fenster", +"None": "Keine", +"New window": "Neues Fenster", +"Open link": "Link öffnen", +"Remove link": "Link entfernen", +"Anchors": "Anker", +"Link...": "Link...", +"Paste or type a link": "Link einfügen oder eingeben", +"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "Diese URL scheint eine E-Mail-Adresse zu sein. Möchten Sie das dazu benötigte mailto: voranstellen?", +"The URL you entered seems to be an external link. Do you want to add the required http:// prefix?": "Diese URL scheint ein externer Link zu sein. Möchten Sie das dazu benötigte http:// voranstellen?", +"The URL you entered seems to be an external link. Do you want to add the required https:// prefix?": "Die eingegebene URL scheint ein externer Link zu sein. Soll das fehlende https:// davor ergänzt werden?", +"Link list": "Linkliste", +"Insert video": "Video einfügen", +"Insert/edit video": "Video einfügen/bearbeiten", +"Insert/edit media": "Medien einfügen/bearbeiten", +"Alternative source": "Alternative Quelle", +"Alternative source URL": "URL der alternativen Quelle", +"Media poster (Image URL)": "Medienposter (Bild-URL)", +"Paste your embed code below:": "Fügen Sie Ihren Einbettungscode unten ein:", +"Embed": "Einbettung", +"Media...": "Medien...", +"Nonbreaking space": "Geschütztes Leerzeichen", +"Page break": "Seitenumbruch", +"Paste as text": "Als Text einfügen", +"Preview": "Vorschau", +"Print": "Drucken", +"Print...": "Drucken...", +"Save": "Speichern", +"Find": "Suchen", +"Replace with": "Ersetzen durch", +"Replace": "Ersetzen", +"Replace all": "Alle ersetzen", +"Previous": "Vorherige", +"Next": "Nächste", +"Find and Replace": "Suchen und Ersetzen", +"Find and replace...": "Suchen und ersetzen...", +"Could not find the specified string.": "Die angegebene Zeichenfolge wurde nicht gefunden.", +"Match case": "Groß-/Kleinschreibung beachten", +"Find whole words only": "Nur ganze Wörter suchen", +"Find in selection": "In Auswahl suchen", +"Insert table": "Tabelle einfügen", +"Table properties": "Tabelleneigenschaften", +"Delete table": "Tabelle löschen", +"Cell": "Zelle", +"Row": "Zeile", +"Column": "Spalte", +"Cell properties": "Zelleigenschaften", +"Merge cells": "Zellen verbinden", +"Split cell": "Zelle aufteilen", +"Insert row before": "Neue Zeile davor einfügen", +"Insert row after": "Neue Zeile danach einfügen", +"Delete row": "Zeile löschen", +"Row properties": "Zeileneigenschaften", +"Cut row": "Zeile ausschneiden", +"Cut column": "Spalte ausschneiden", +"Copy row": "Zeile kopieren", +"Copy column": "Spalte kopieren", +"Paste row before": "Zeile davor einfügen", +"Paste column before": "Spalte davor einfügen", +"Paste row after": "Zeile danach einfügen", +"Paste column after": "Spalte danach einfügen", +"Insert column before": "Neue Spalte davor einfügen", +"Insert column after": "Neue Spalte danach einfügen", +"Delete column": "Spalte löschen", +"Cols": "Spalten", +"Rows": "Zeilen", +"Width": "Breite", +"Height": "Höhe", +"Cell spacing": "Zellenabstand", +"Cell padding": "Zelleninnenabstand", +"Row clipboard actions": "Zeilen-Zwischenablage-Aktionen", +"Column clipboard actions": "Spalten-Zwischenablage-Aktionen", +"Table styles": "Tabellenstil", +"Cell styles": "Zellstil", +"Column header": "Spaltenkopf", +"Row header": "Zeilenkopf", +"Table caption": "Tabellenbeschriftung", +"Caption": "Beschriftung", +"Show caption": "Beschriftung anzeigen", +"Left": "Links", +"Center": "Zentriert", +"Right": "Rechts", +"Cell type": "Zelltyp", +"Scope": "Bereich", +"Alignment": "Ausrichtung", +"Horizontal align": "Horizontal ausrichten", +"Vertical align": "Vertikal ausrichten", +"Top": "Oben", +"Middle": "Mitte", +"Bottom": "Unten", +"Header cell": "Kopfzelle", +"Row group": "Zeilengruppe", +"Column group": "Spaltengruppe", +"Row type": "Zeilentyp", +"Header": "Kopfzeile", +"Body": "Inhalt", +"Footer": "Fußzeile", +"Border color": "Rahmenfarbe", +"Solid": "Durchgezogen", +"Dotted": "Gepunktet", +"Dashed": "Gestrichelt", +"Double": "Doppelt", +"Groove": "Gekantet", +"Ridge": "Eingeritzt", +"Inset": "Eingelassen", +"Outset": "Hervorstehend", +"Hidden": "Unsichtbar", +"Insert template...": "Vorlage einfügen...", +"Templates": "Vorlagen", +"Template": "Vorlage", +"Insert Template": "Vorlage einfügen", +"Text color": "Textfarbe", +"Background color": "Hintergrundfarbe", +"Custom...": "Benutzerdefiniert...", +"Custom color": "Benutzerdefinierte Farbe", +"No color": "Keine Farbe", +"Remove color": "Farbauswahl aufheben", +"Show blocks": "Blöcke anzeigen", +"Show invisible characters": "Unsichtbare Zeichen anzeigen", +"Word count": "Anzahl der Wörter", +"Count": "Anzahl", +"Document": "Dokument", +"Selection": "Auswahl", +"Words": "Wörter", +"Words: {0}": "Wortzahl: {0}", +"{0} words": "{0} Wörter", +"File": "Datei", +"Edit": "Bearbeiten", +"Insert": "Einfügen", +"View": "Ansicht", +"Format": "Format", +"Table": "Tabelle", +"Tools": "Werkzeuge", +"Powered by {0}": "Betrieben von {0}", +"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Rich-Text-Bereich. Drücken Sie Alt+F9 für das Menü. Drücken Sie Alt+F10 für die Symbolleiste. Drücken Sie Alt+0 für Hilfe.", +"Image title": "Bildtitel", +"Border width": "Rahmenbreite", +"Border style": "Rahmenstil", +"Error": "Fehler", +"Warn": "Warnung", +"Valid": "Gültig", +"To open the popup, press Shift+Enter": "Drücken Sie Umschalt+Eingabe, um das Popup-Fenster zu öffnen.", +"Rich Text Area": "Rich-Text-Area", +"Rich Text Area. Press ALT-0 for help.": "Rich-Text-Bereich. Drücken Sie Alt+0 für Hilfe.", +"System Font": "Betriebssystemschriftart", +"Failed to upload image: {0}": "Bild konnte nicht hochgeladen werden: {0}", +"Failed to load plugin: {0} from url {1}": "Plugin konnte nicht geladen werden: {0} von URL {1}", +"Failed to load plugin url: {0}": "Plugin-URL konnte nicht geladen werden: {0}", +"Failed to initialize plugin: {0}": "Plugin konnte nicht initialisiert werden: {0}", +"example": "Beispiel", +"Search": "Suchen", +"All": "Alle", +"Currency": "Währung", +"Text": "Text", +"Quotations": "Anführungszeichen", +"Mathematical": "Mathematisch", +"Extended Latin": "Erweitertes Latein", +"Symbols": "Symbole", +"Arrows": "Pfeile", +"User Defined": "Benutzerdefiniert", +"dollar sign": "Dollarzeichen", +"currency sign": "Währungssymbol", +"euro-currency sign": "Eurozeichen", +"colon sign": "Doppelpunkt", +"cruzeiro sign": "Cruzeirozeichen", +"french franc sign": "Franczeichen", +"lira sign": "Lirezeichen", +"mill sign": "Millzeichen", +"naira sign": "Nairazeichen", +"peseta sign": "Pesetazeichen", +"rupee sign": "Rupiezeichen", +"won sign": "Wonzeichen", +"new sheqel sign": "Schekelzeichen", +"dong sign": "Dongzeichen", +"kip sign": "Kipzeichen", +"tugrik sign": "Tugrikzeichen", +"drachma sign": "Drachmezeichen", +"german penny symbol": "Pfennigzeichen", +"peso sign": "Pesozeichen", +"guarani sign": "Guaranizeichen", +"austral sign": "Australzeichen", +"hryvnia sign": "Hrywnjazeichen", +"cedi sign": "Cedizeichen", +"livre tournois sign": "Livrezeichen", +"spesmilo sign": "Spesmilozeichen", +"tenge sign": "Tengezeichen", +"indian rupee sign": "Indisches Rupiezeichen", +"turkish lira sign": "Türkisches Lirazeichen", +"nordic mark sign": "Zeichen nordische Mark", +"manat sign": "Manatzeichen", +"ruble sign": "Rubelzeichen", +"yen character": "Yenzeichen", +"yuan character": "Yuanzeichen", +"yuan character, in hong kong and taiwan": "Yuanzeichen in Hongkong und Taiwan", +"yen/yuan character variant one": "Yen-/Yuanzeichen Variante 1", +"Emojis": "Emojis", +"Emojis...": "Emojis...", +"Loading emojis...": "Lade Emojis...", +"Could not load emojis": "Emojis konnten nicht geladen werden", +"People": "Menschen", +"Animals and Nature": "Tiere und Natur", +"Food and Drink": "Essen und Trinken", +"Activity": "Aktivität", +"Travel and Places": "Reisen und Orte", +"Objects": "Objekte", +"Flags": "Flaggen", +"Characters": "Zeichen", +"Characters (no spaces)": "Zeichen (ohne Leerzeichen)", +"{0} characters": "{0} Zeichen", +"Error: Form submit field collision.": "Fehler: Kollision der Formularbestätigungsfelder.", +"Error: No form element found.": "Fehler: Kein Formularelement gefunden.", +"Color swatch": "Farbpalette", +"Color Picker": "Farbwahl", +"Invalid hex color code: {0}": "Ungültiger Hexadezimal-Farbwert: {0}", +"Invalid input": "Ungültige Eingabe", +"R": "R", +"Red component": "Rotanteil", +"G": "G", +"Green component": "Grünanteil", +"B": "B", +"Blue component": "Blauanteil", +"#": "#", +"Hex color code": "Hexadezimal-Farbwert", +"Range 0 to 255": "Spanne 0 bis 255", +"Turquoise": "Türkis", +"Green": "Grün", +"Blue": "Blau", +"Purple": "Violett", +"Navy Blue": "Marineblau", +"Dark Turquoise": "Dunkeltürkis", +"Dark Green": "Dunkelgrün", +"Medium Blue": "Mittleres Blau", +"Medium Purple": "Mittelviolett", +"Midnight Blue": "Mitternachtsblau", +"Yellow": "Gelb", +"Orange": "Orange", +"Red": "Rot", +"Light Gray": "Hellgrau", +"Gray": "Grau", +"Dark Yellow": "Dunkelgelb", +"Dark Orange": "Dunkelorange", +"Dark Red": "Dunkelrot", +"Medium Gray": "Mittelgrau", +"Dark Gray": "Dunkelgrau", +"Light Green": "Hellgrün", +"Light Yellow": "Hellgelb", +"Light Red": "Hellrot", +"Light Purple": "Helllila", +"Light Blue": "Hellblau", +"Dark Purple": "Dunkellila", +"Dark Blue": "Dunkelblau", +"Black": "Schwarz", +"White": "Weiß", +"Switch to or from fullscreen mode": "Vollbildmodus umschalten", +"Open help dialog": "Hilfe-Dialog öffnen", +"history": "Historie", +"styles": "Stile", +"formatting": "Formatierung", +"alignment": "Ausrichtung", +"indentation": "Einrückungen", +"Font": "Schriftart", +"Size": "Schriftgröße", +"More...": "Mehr...", +"Select...": "Auswahl...", +"Preferences": "Einstellungen", +"Yes": "Ja", +"No": "Nein", +"Keyboard Navigation": "Tastaturnavigation", +"Version": "Version", +"Code view": "Code Ansicht", +"Open popup menu for split buttons": "Öffne Popup Menge um Buttons zu trennen", +"List Properties": "Liste Eigenschaften", +"List properties...": "Liste Eigenschaften", +"Start list at number": "Beginne Liste mit Nummer", +"Line height": "Liniendicke", +"Dropped file type is not supported": "Hereingezogener Dateityp wird nicht unterstützt", +"Loading...": "Wird geladen...", +"ImageProxy HTTP error: Rejected request": "Image Proxy HTTP Fehler: Abgewiesene Anfrage", +"ImageProxy HTTP error: Could not find Image Proxy": "Image Proxy HTTP Fehler: Kann Image Proxy nicht finden", +"ImageProxy HTTP error: Incorrect Image Proxy URL": "Image Proxy HTTP Fehler: Falsche Image Proxy URL", +"ImageProxy HTTP error: Unknown ImageProxy error": "Image Proxy HTTP Fehler: Unbekannter Image Proxy Fehler" +}); \ No newline at end of file diff --git a/public/plugins/tinymce/license.txt b/public/plugins/tinymce/license.txt new file mode 100644 index 000000000..3a49f66fd --- /dev/null +++ b/public/plugins/tinymce/license.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Ephox Corporation DBA Tiny Technologies, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/public/plugins/tinymce/models/dom/model.min.js b/public/plugins/tinymce/models/dom/model.min.js new file mode 100644 index 000000000..84bd6b77f --- /dev/null +++ b/public/plugins/tinymce/models/dom/model.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.ModelManager");const t=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(o=n=e,(r=String).prototype.isPrototypeOf(o)||(null===(s=n.constructor)||void 0===s?void 0:s.name)===r.name)?"string":t;var o,n,r,s})(t)===e,o=e=>t=>typeof t===e,n=e=>t=>e===t,r=t("string"),s=t("object"),l=t("array"),a=n(null),c=o("boolean"),i=n(void 0),m=e=>!(e=>null==e)(e),d=o("function"),u=o("number"),f=()=>{},g=e=>()=>e,h=e=>e,p=(e,t)=>e===t;function w(e,...t){return(...o)=>{const n=t.concat(o);return e.apply(null,n)}}const b=e=>t=>!e(t),v=e=>e(),y=g(!1),x=g(!0);class C{constructor(e,t){this.tag=e,this.value=t}static some(e){return new C(!0,e)}static none(){return C.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?C.some(e(this.value)):C.none()}bind(e){return this.tag?e(this.value):C.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:C.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return m(e)?C.some(e):C.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}C.singletonNone=new C(!1);const S=Array.prototype.slice,T=Array.prototype.indexOf,R=Array.prototype.push,D=(e,t)=>{return o=e,n=t,T.call(o,n)>-1;var o,n},O=(e,t)=>{for(let o=0,n=e.length;o{const o=[];for(let n=0;n{const o=e.length,n=new Array(o);for(let r=0;r{for(let o=0,n=e.length;o{const o=[],n=[];for(let r=0,s=e.length;r{const o=[];for(let n=0,r=e.length;n(((e,t)=>{for(let o=e.length-1;o>=0;o--)t(e[o],o)})(e,((e,n)=>{o=t(o,e,n)})),o),W=(e,t,o)=>(N(e,((e,n)=>{o=t(o,e,n)})),o),L=(e,t)=>((e,t,o)=>{for(let n=0,r=e.length;n{for(let o=0,n=e.length;o{const t=[];for(let o=0,n=e.length;oM(E(e,t)),I=(e,t)=>{for(let o=0,n=e.length;o{const o={};for(let n=0,r=e.length;nt>=0&&tF(e,0),q=e=>F(e,e.length-1),V=(e,t)=>{for(let o=0;o{const o=$(e);for(let n=0,r=o.length;nY(e,((e,o)=>({k:o,v:t(e,o)}))),Y=(e,t)=>{const o={};return G(e,((e,n)=>{const r=t(e,n);o[r.k]=r.v})),o},J=(e,t)=>{const o=[];return G(e,((e,n)=>{o.push(t(e,n))})),o},Q=e=>J(e,h),X=(e,t)=>U.call(e,t);"undefined"!=typeof window?window:Function("return this;")();const Z=e=>e.dom.nodeName.toLowerCase(),ee=e=>e.dom.nodeType,te=e=>t=>ee(t)===e,oe=e=>8===ee(e)||"#comment"===Z(e),ne=te(1),re=te(3),se=te(9),le=te(11),ae=e=>t=>ne(t)&&Z(t)===e,ce=(e,t,o)=>{if(!(r(o)||c(o)||u(o)))throw console.error("Invalid call to Attribute.set. Key ",t,":: Value ",o,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(t,o+"")},ie=(e,t,o)=>{ce(e.dom,t,o)},me=(e,t)=>{const o=e.dom;G(t,((e,t)=>{ce(o,t,e)}))},de=(e,t)=>{const o=e.dom.getAttribute(t);return null===o?void 0:o},ue=(e,t)=>C.from(de(e,t)),fe=(e,t)=>{e.dom.removeAttribute(t)},ge=e=>W(e.dom.attributes,((e,t)=>(e[t.name]=t.value,e)),{}),he=e=>{if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}},pe={fromHtml:(e,t)=>{const o=(t||document).createElement("div");if(o.innerHTML=e,!o.hasChildNodes()||o.childNodes.length>1){const t="HTML does not have a single root node";throw console.error(t,e),new Error(t)}return he(o.childNodes[0])},fromTag:(e,t)=>{const o=(t||document).createElement(e);return he(o)},fromText:(e,t)=>{const o=(t||document).createTextNode(e);return he(o)},fromDom:he,fromPoint:(e,t,o)=>C.from(e.dom.elementFromPoint(t,o)).map(he)},we=(e,t)=>{const o=e.dom;if(1!==o.nodeType)return!1;{const e=o;if(void 0!==e.matches)return e.matches(t);if(void 0!==e.msMatchesSelector)return e.msMatchesSelector(t);if(void 0!==e.webkitMatchesSelector)return e.webkitMatchesSelector(t);if(void 0!==e.mozMatchesSelector)return e.mozMatchesSelector(t);throw new Error("Browser lacks native selectors")}},be=e=>1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType||0===e.childElementCount,ve=(e,t)=>{const o=void 0===t?document:t.dom;return be(o)?C.none():C.from(o.querySelector(e)).map(pe.fromDom)},ye=(e,t)=>e.dom===t.dom,xe=(e,t)=>{const o=e.dom,n=t.dom;return o!==n&&o.contains(n)},Ce=we,Se=e=>pe.fromDom(e.dom.ownerDocument),Te=e=>se(e)?e:Se(e),Re=e=>C.from(e.dom.parentNode).map(pe.fromDom),De=(e,t)=>{const o=d(t)?t:y;let n=e.dom;const r=[];for(;null!==n.parentNode&&void 0!==n.parentNode;){const e=n.parentNode,t=pe.fromDom(e);if(r.push(t),!0===o(t))break;n=e}return r},Oe=e=>C.from(e.dom.previousSibling).map(pe.fromDom),ke=e=>C.from(e.dom.nextSibling).map(pe.fromDom),Ee=e=>E(e.dom.childNodes,pe.fromDom),Ne=(e,t)=>{const o=e.dom.childNodes;return C.from(o[t]).map(pe.fromDom)},Be=(e,t)=>{Re(e).each((o=>{o.dom.insertBefore(t.dom,e.dom)}))},ze=(e,t)=>{ke(e).fold((()=>{Re(e).each((e=>{We(e,t)}))}),(e=>{Be(e,t)}))},Ae=(e,t)=>{const o=(e=>Ne(e,0))(e);o.fold((()=>{We(e,t)}),(o=>{e.dom.insertBefore(t.dom,o.dom)}))},We=(e,t)=>{e.dom.appendChild(t.dom)},Le=(e,t)=>{Be(e,t),We(t,e)},_e=(e,t)=>{N(t,((o,n)=>{const r=0===n?e:t[n-1];ze(r,o)}))},Me=(e,t)=>{N(t,(t=>{We(e,t)}))},je=e=>{e.dom.textContent="",N(Ee(e),(e=>{Ie(e)}))},Ie=e=>{const t=e.dom;null!==t.parentNode&&t.parentNode.removeChild(t)},Pe=e=>{const t=Ee(e);t.length>0&&_e(e,t),Ie(e)},Fe=(e,t)=>pe.fromDom(e.dom.cloneNode(t)),He=e=>Fe(e,!1),qe=e=>Fe(e,!0),Ve=(e,t)=>{const o=pe.fromTag(t),n=ge(e);return me(o,n),o},$e=["tfoot","thead","tbody","colgroup"],Ue=(e,t,o)=>({element:e,rowspan:t,colspan:o}),Ge=(e,t,o)=>({element:e,cells:t,section:o}),Ke=(e,t,o)=>({element:e,isNew:t,isLocked:o}),Ye=(e,t,o,n)=>({element:e,cells:t,section:o,isNew:n}),Je=d(Element.prototype.attachShadow)&&d(Node.prototype.getRootNode),Qe=g(Je),Xe=Je?e=>pe.fromDom(e.dom.getRootNode()):Te,Ze=e=>pe.fromDom(e.dom.host),et=e=>{const t=re(e)?e.dom.parentNode:e.dom;if(null==t||null===t.ownerDocument)return!1;const o=t.ownerDocument;return(e=>{const t=Xe(e);return le(o=t)&&m(o.dom.host)?C.some(t):C.none();var o})(pe.fromDom(t)).fold((()=>o.body.contains(t)),(n=et,r=Ze,e=>n(r(e))));var n,r},tt=e=>{const t=e.dom.body;if(null==t)throw new Error("Body is not available yet");return pe.fromDom(t)},ot=(e,t)=>{let o=[];return N(Ee(e),(e=>{t(e)&&(o=o.concat([e])),o=o.concat(ot(e,t))})),o},nt=(e,t,o)=>((e,o,n)=>z(De(e,n),(e=>we(e,t))))(e,0,o),rt=(e,t)=>((e,o)=>z(Ee(e),(e=>we(e,t))))(e),st=(e,t)=>((e,t)=>{const o=void 0===t?document:t.dom;return be(o)?[]:E(o.querySelectorAll(e),pe.fromDom)})(t,e);var lt=(e,t,o,n,r)=>e(o,n)?C.some(o):d(r)&&r(o)?C.none():t(o,n,r);const at=(e,t,o)=>{let n=e.dom;const r=d(o)?o:y;for(;n.parentNode;){n=n.parentNode;const e=pe.fromDom(n);if(t(e))return C.some(e);if(r(e))break}return C.none()},ct=(e,t,o)=>at(e,(e=>we(e,t)),o),it=(e,t)=>((e,o)=>L(e.dom.childNodes,(e=>{return o=pe.fromDom(e),we(o,t);var o})).map(pe.fromDom))(e),mt=(e,t)=>ve(t,e),dt=(e,t,o)=>lt(((e,t)=>we(e,t)),ct,e,t,o),ut=(e,t,o=p)=>e.exists((e=>o(e,t))),ft=e=>{const t=[],o=e=>{t.push(e)};for(let t=0;te?C.some(t):C.none(),ht=(e,t,o)=>""===t||e.length>=t.length&&e.substr(o,o+t.length)===t,pt=(e,t,o=0,n)=>{const r=e.indexOf(t,o);return-1!==r&&(!!i(n)||r+t.length<=n)},wt=(e,t)=>ht(e,t,0),bt=(e,t)=>ht(e,t,e.length-t.length),vt=(e=>t=>t.replace(e,""))(/^\s+|\s+$/g),yt=e=>e.length>0,xt=e=>void 0!==e.style&&d(e.style.getPropertyValue),Ct=(e,t,o)=>{if(!r(o))throw console.error("Invalid call to CSS.set. Property ",t,":: Value ",o,":: Element ",e),new Error("CSS value must be a string: "+o);xt(e)&&e.style.setProperty(t,o)},St=(e,t,o)=>{const n=e.dom;Ct(n,t,o)},Tt=(e,t)=>{const o=e.dom;G(t,((e,t)=>{Ct(o,t,e)}))},Rt=(e,t)=>{const o=e.dom,n=window.getComputedStyle(o).getPropertyValue(t);return""!==n||et(e)?n:Dt(o,t)},Dt=(e,t)=>xt(e)?e.style.getPropertyValue(t):"",Ot=(e,t)=>{const o=e.dom,n=Dt(o,t);return C.from(n).filter((e=>e.length>0))},kt=(e,t)=>{((e,t)=>{xt(e)&&e.style.removeProperty(t)})(e.dom,t),ut(ue(e,"style").map(vt),"")&&fe(e,"style")},Et=(e,t,o=0)=>ue(e,t).map((e=>parseInt(e,10))).getOr(o),Nt=(e,t)=>Et(e,t,1),Bt=e=>ae("col")(e)?Et(e,"span",1)>1:Nt(e,"colspan")>1,zt=e=>Nt(e,"rowspan")>1,At=(e,t)=>parseInt(Rt(e,t),10),Wt=g(10),Lt=g(10),_t=(e,t)=>Mt(e,t,x),Mt=(e,t,o)=>j(Ee(e),(e=>we(e,t)?o(e)?[e]:[]:Mt(e,t,o))),jt=(e,t)=>((e,t,o=y)=>o(t)?C.none():D(e,Z(t))?C.some(t):ct(t,e.join(","),(e=>we(e,"table")||o(e))))(["td","th"],e,t),It=e=>_t(e,"th,td"),Pt=e=>we(e,"colgroup")?rt(e,"col"):j(qt(e),(e=>rt(e,"col"))),Ft=(e,t)=>dt(e,"table",t),Ht=e=>_t(e,"tr"),qt=e=>Ft(e).fold(g([]),(e=>rt(e,"colgroup"))),Vt=(e,t)=>E(e,(e=>{if("colgroup"===Z(e)){const t=E(Pt(e),(e=>{const t=Et(e,"span",1);return Ue(e,1,t)}));return Ge(e,t,"colgroup")}{const o=E(It(e),(e=>{const t=Et(e,"rowspan",1),o=Et(e,"colspan",1);return Ue(e,t,o)}));return Ge(e,o,t(e))}})),$t=e=>Re(e).map((e=>{const t=Z(e);return(e=>D($e,e))(t)?t:"tbody"})).getOr("tbody"),Ut=e=>{const t=Ht(e),o=[...qt(e),...t];return Vt(o,$t)},Gt=e=>{let t,o=!1;return(...n)=>(o||(o=!0,t=e.apply(null,n)),t)},Kt=()=>Yt(0,0),Yt=(e,t)=>({major:e,minor:t}),Jt={nu:Yt,detect:(e,t)=>{const o=String(t).toLowerCase();return 0===e.length?Kt():((e,t)=>{const o=((e,t)=>{for(let o=0;oNumber(t.replace(o,"$"+e));return Yt(n(1),n(2))})(e,o)},unknown:Kt},Qt=(e,t)=>{const o=String(t).toLowerCase();return L(e,(e=>e.search(o)))},Xt=/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,Zt=e=>t=>pt(t,e),eo=[{name:"Edge",versionRegexes:[/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],search:e=>pt(e,"edge/")&&pt(e,"chrome")&&pt(e,"safari")&&pt(e,"applewebkit")},{name:"Chromium",brand:"Chromium",versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/,Xt],search:e=>pt(e,"chrome")&&!pt(e,"chromeframe")},{name:"IE",versionRegexes:[/.*?msie\ ?([0-9]+)\.([0-9]+).*/,/.*?rv:([0-9]+)\.([0-9]+).*/],search:e=>pt(e,"msie")||pt(e,"trident")},{name:"Opera",versionRegexes:[Xt,/.*?opera\/([0-9]+)\.([0-9]+).*/],search:Zt("opera")},{name:"Firefox",versionRegexes:[/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],search:Zt("firefox")},{name:"Safari",versionRegexes:[Xt,/.*?cpu os ([0-9]+)_([0-9]+).*/],search:e=>(pt(e,"safari")||pt(e,"mobile/"))&&pt(e,"applewebkit")}],to=[{name:"Windows",search:Zt("win"),versionRegexes:[/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]},{name:"iOS",search:e=>pt(e,"iphone")||pt(e,"ipad"),versionRegexes:[/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,/.*cpu os ([0-9]+)_([0-9]+).*/,/.*cpu iphone os ([0-9]+)_([0-9]+).*/]},{name:"Android",search:Zt("android"),versionRegexes:[/.*?android\ ?([0-9]+)\.([0-9]+).*/]},{name:"macOS",search:Zt("mac os x"),versionRegexes:[/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]},{name:"Linux",search:Zt("linux"),versionRegexes:[]},{name:"Solaris",search:Zt("sunos"),versionRegexes:[]},{name:"FreeBSD",search:Zt("freebsd"),versionRegexes:[]},{name:"ChromeOS",search:Zt("cros"),versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/]}],oo={browsers:g(eo),oses:g(to)},no="Edge",ro="Chromium",so="Opera",lo="Firefox",ao="Safari",co=e=>{const t=e.current,o=e.version,n=e=>()=>t===e;return{current:t,version:o,isEdge:n(no),isChromium:n(ro),isIE:n("IE"),isOpera:n(so),isFirefox:n(lo),isSafari:n(ao)}},io=()=>co({current:void 0,version:Jt.unknown()}),mo=co,uo=(g(no),g(ro),g("IE"),g(so),g(lo),g(ao),"Windows"),fo="Android",go="Linux",ho="macOS",po="Solaris",wo="FreeBSD",bo="ChromeOS",vo=e=>{const t=e.current,o=e.version,n=e=>()=>t===e;return{current:t,version:o,isWindows:n(uo),isiOS:n("iOS"),isAndroid:n(fo),isMacOS:n(ho),isLinux:n(go),isSolaris:n(po),isFreeBSD:n(wo),isChromeOS:n(bo)}},yo=()=>vo({current:void 0,version:Jt.unknown()}),xo=vo,Co=(g(uo),g("iOS"),g(fo),g(go),g(ho),g(po),g(wo),g(bo),e=>window.matchMedia(e).matches);let So=Gt((()=>((e,t,o)=>{const n=oo.browsers(),r=oo.oses(),s=t.bind((e=>((e,t)=>V(t.brands,(t=>{const o=t.brand.toLowerCase();return L(e,(e=>{var t;return o===(null===(t=e.brand)||void 0===t?void 0:t.toLowerCase())})).map((e=>({current:e.name,version:Jt.nu(parseInt(t.version,10),0)})))})))(n,e))).orThunk((()=>((e,t)=>Qt(e,t).map((e=>{const o=Jt.detect(e.versionRegexes,t);return{current:e.name,version:o}})))(n,e))).fold(io,mo),l=((e,t)=>Qt(e,t).map((e=>{const o=Jt.detect(e.versionRegexes,t);return{current:e.name,version:o}})))(r,e).fold(yo,xo),a=((e,t,o,n)=>{const r=e.isiOS()&&!0===/ipad/i.test(o),s=e.isiOS()&&!r,l=e.isiOS()||e.isAndroid(),a=l||n("(pointer:coarse)"),c=r||!s&&l&&n("(min-device-width:768px)"),i=s||l&&!c,m=t.isSafari()&&e.isiOS()&&!1===/safari/i.test(o),d=!i&&!c&&!m;return{isiPad:g(r),isiPhone:g(s),isTablet:g(c),isPhone:g(i),isTouch:g(a),isAndroid:e.isAndroid,isiOS:e.isiOS,isWebView:g(m),isDesktop:g(d)}})(l,s,e,o);return{browser:s,os:l,deviceType:a}})(navigator.userAgent,C.from(navigator.userAgentData),Co)));const To=()=>So(),Ro=(e,t)=>{const o=o=>{const n=t(o);if(n<=0||null===n){const t=Rt(o,e);return parseFloat(t)||0}return n},n=(e,t)=>W(t,((t,o)=>{const n=Rt(e,o),r=void 0===n?0:parseInt(n,10);return isNaN(r)?t:t+r}),0);return{set:(t,o)=>{if(!u(o)&&!o.match(/^[0-9]+$/))throw new Error(e+".set accepts only positive integer values. Value was "+o);const n=t.dom;xt(n)&&(n.style[e]=o+"px")},get:o,getOuter:o,aggregate:n,max:(e,t,o)=>{const r=n(e,o);return t>r?t-r:0}}},Do=(e,t,o)=>((e,t)=>(e=>{const t=parseFloat(e);return isNaN(t)?C.none():C.some(t)})(e).getOr(t))(Rt(e,t),o),Oo=Ro("width",(e=>e.dom.offsetWidth)),ko=e=>Oo.get(e),Eo=e=>Oo.getOuter(e),No=e=>((e,t)=>{const o=e.dom,n=o.getBoundingClientRect().width||o.offsetWidth;return"border-box"===t?n:((e,t,o,n)=>t-Do(e,"padding-left",0)-Do(e,"padding-right",0)-Do(e,"border-left-width",0)-Do(e,"border-right-width",0))(e,n)})(e,"content-box"),Bo=(e,t,o)=>{const n=e.cells,r=n.slice(0,t),s=n.slice(t),l=r.concat(o).concat(s);return Wo(e,l)},zo=(e,t,o)=>Bo(e,t,[o]),Ao=(e,t,o)=>{e.cells[t]=o},Wo=(e,t)=>Ye(e.element,t,e.section,e.isNew),Lo=(e,t)=>e.cells[t],_o=(e,t)=>Lo(e,t).element,Mo=e=>e.cells.length,jo=e=>{const t=B(e,(e=>"colgroup"===e.section));return{rows:t.fail,cols:t.pass}},Io=(e,t,o)=>{const n=E(e.cells,o);return Ye(t(e.element),n,e.section,!0)},Po="data-snooker-locked-cols",Fo=e=>ue(e,Po).bind((e=>C.from(e.match(/\d+/g)))).map((e=>P(e,x))),Ho=e=>{const t=W(jo(e).rows,((e,t)=>(N(t.cells,((t,o)=>{t.isLocked&&(e[o]=!0)})),e)),{}),o=J(t,((e,t)=>parseInt(t,10)));return((e,t)=>{const o=S.call(e,0);return o.sort(void 0),o})(o)},qo=(e,t)=>e+","+t,Vo=(e,t)=>{const o=j(e.all,(e=>e.cells));return z(o,t)},$o=e=>{const t={},o=[],n=H(e).map((e=>e.element)).bind(Ft).bind(Fo).getOr({});let r=0,s=0,l=0;const{pass:a,fail:c}=B(e,(e=>"colgroup"===e.section));N(c,(e=>{const a=[];N(e.cells,(e=>{let o=0;for(;void 0!==t[qo(l,o)];)o++;const r=((e,t)=>X(e,t)&&void 0!==e[t]&&null!==e[t])(n,o.toString()),c=((e,t,o,n,r,s)=>({element:e,rowspan:t,colspan:o,row:n,column:r,isLocked:s}))(e.element,e.rowspan,e.colspan,l,o,r);for(let n=0;n{const t=(e=>{const t={};let o=0;return N(e.cells,(e=>{const n=e.colspan;k(n,(r=>{const s=o+r;t[s]=((e,t,o)=>({element:e,colspan:t,column:o}))(e.element,n,s)})),o+=n})),t})(e),o=((e,t)=>({element:e,columns:t}))(e.element,Q(t));return{colgroups:[o],columns:t}})).getOrThunk((()=>({colgroups:[],columns:{}}))),d=((e,t)=>({rows:e,columns:t}))(r,s);return{grid:d,access:t,all:o,columns:i,colgroups:m}},Uo=e=>{const t=Ut(e);return $o(t)},Go=$o,Ko=(e,t,o)=>C.from(e.access[qo(t,o)]),Yo=(e,t,o)=>{const n=Vo(e,(e=>o(t,e.element)));return n.length>0?C.some(n[0]):C.none()},Jo=Vo,Qo=e=>j(e.all,(e=>e.cells)),Xo=e=>Q(e.columns),Zo=e=>$(e.columns).length>0,en=(e,t)=>C.from(e.columns[t]),tn=(e,t=x)=>{const o=e.grid,n=k(o.columns,h),r=k(o.rows,h);return E(n,(o=>on((()=>j(r,(t=>Ko(e,t,o).filter((e=>e.column===o)).toArray()))),(e=>1===e.colspan&&t(e.element)),(()=>Ko(e,0,o)))))},on=(e,t,o)=>{const n=e();return L(n,t).orThunk((()=>C.from(n[0]).orThunk(o))).map((e=>e.element))},nn=e=>{const t=e.grid,o=k(t.rows,h),n=k(t.columns,h);return E(o,(t=>on((()=>j(n,(o=>Ko(e,t,o).filter((e=>e.row===t)).fold(g([]),(e=>[e]))))),(e=>1===e.rowspan),(()=>Ko(e,t,0)))))},rn=(e,t)=>o=>"rtl"===sn(o)?t:e,sn=e=>"rtl"===Rt(e,"direction")?"rtl":"ltr",ln=Ro("height",(e=>{const t=e.dom;return et(e)?t.getBoundingClientRect().height:t.offsetHeight})),an=e=>ln.get(e),cn=e=>ln.getOuter(e),mn=(e,t)=>({left:e,top:t,translate:(o,n)=>mn(e+o,t+n)}),dn=mn,un=(e,t)=>void 0!==e?e:void 0!==t?t:0,fn=e=>{const t=e.dom.ownerDocument,o=t.body,n=t.defaultView,r=t.documentElement;if(o===e.dom)return dn(o.offsetLeft,o.offsetTop);const s=un(null==n?void 0:n.pageYOffset,r.scrollTop),l=un(null==n?void 0:n.pageXOffset,r.scrollLeft),a=un(r.clientTop,o.clientTop),c=un(r.clientLeft,o.clientLeft);return gn(e).translate(l-c,s-a)},gn=e=>{const t=e.dom,o=t.ownerDocument.body;return o===t?dn(o.offsetLeft,o.offsetTop):et(e)?(e=>{const t=e.getBoundingClientRect();return dn(t.left,t.top)})(t):dn(0,0)},hn=(e,t)=>({row:e,y:t}),pn=(e,t)=>({col:e,x:t}),wn=e=>fn(e).left+Eo(e),bn=e=>fn(e).left,vn=(e,t)=>pn(e,bn(t)),yn=(e,t)=>pn(e,wn(t)),xn=e=>fn(e).top,Cn=(e,t)=>hn(e,xn(t)),Sn=(e,t)=>hn(e,xn(t)+cn(t)),Tn=(e,t,o)=>{if(0===o.length)return[];const n=E(o.slice(1),((t,o)=>t.map((t=>e(o,t))))),r=o[o.length-1].map((e=>t(o.length-1,e)));return n.concat([r])},Rn={delta:h,positions:e=>Tn(Cn,Sn,e),edge:xn},Dn=rn({delta:h,edge:bn,positions:e=>Tn(vn,yn,e)},{delta:e=>-e,edge:wn,positions:e=>Tn(yn,vn,e)}),On={delta:(e,t)=>Dn(t).delta(e,t),positions:(e,t)=>Dn(t).positions(e,t),edge:e=>Dn(e).edge(e)},kn={unsupportedLength:["em","ex","cap","ch","ic","rem","lh","rlh","vw","vh","vi","vb","vmin","vmax","cm","mm","Q","in","pc","pt","px"],fixed:["px","pt"],relative:["%"],empty:[""]},En=(()=>{const e="[0-9]+",t="[eE][+-]?[0-9]+",o=e=>`(?:${e})?`,n=["Infinity","[0-9]+\\."+o(e)+o(t),"\\.[0-9]+"+o(t),e+o(t)].join("|");return new RegExp(`^([+-]?(?:${n}))(.*)$`)})(),Nn=/(\d+(\.\d+)?)%/,Bn=/(\d+(\.\d+)?)px|em/,zn=ae("col"),An=(e,t,o)=>{const n=(r=e,C.from(r.dom.parentElement).map(pe.fromDom)).getOrThunk((()=>tt(Se(e))));var r;return t(e)/o(n)*100},Wn=(e,t)=>{St(e,"width",t+"px")},Ln=(e,t)=>{St(e,"width",t+"%")},_n=(e,t)=>{St(e,"height",t+"px")},Mn=e=>{const t=(e=>{return Do(t=e,"height",t.dom.offsetHeight)+"px";var t})(e);return t?((e,t,o,n)=>{const r=parseFloat(e);return bt(e,"%")&&"table"!==Z(t)?((e,t,o,n)=>{const r=Ft(e).map((e=>{const n=o(e);return Math.floor(t/100*n)})).getOr(t);return n(e,r),r})(t,r,o,n):r})(t,e,an,_n):an(e)},jn=(e,t)=>Ot(e,t).orThunk((()=>ue(e,t).map((e=>e+"px")))),In=e=>jn(e,"width"),Pn=e=>An(e,ko,No),Fn=e=>{return zn(e)?ko(e):Do(t=e,"width",t.dom.offsetWidth);var t},Hn=e=>((e,t,o)=>o(e)/Nt(e,"rowspan"))(e,0,Mn),qn=(e,t,o)=>{St(e,"width",t+o)},Vn=e=>An(e,ko,No)+"%",$n=g(Nn),Un=ae("col"),Gn=e=>In(e).getOrThunk((()=>Fn(e)+"px")),Kn=e=>{return(t=e,jn(t,"height")).getOrThunk((()=>Hn(e)+"px"));var t},Yn=(e,t,o,n,r,s)=>e.filter(n).fold((()=>s(((e,t)=>{if(t<0||t>=e.length-1)return C.none();const o=e[t].fold((()=>{const o=(e=>{const t=S.call(e,0);return t.reverse(),t})(e.slice(0,t));return V(o,((e,t)=>e.map((e=>({value:e,delta:t+1})))))}),(e=>C.some({value:e,delta:0}))),n=e[t+1].fold((()=>{const o=e.slice(t+1);return V(o,((e,t)=>e.map((e=>({value:e,delta:t+1})))))}),(e=>C.some({value:e,delta:1})));return o.bind((e=>n.map((t=>{const o=t.delta+e.delta;return Math.abs(t.value-e.value)/o}))))})(o,t))),(e=>r(e))),Jn=(e,t,o,n)=>{const r=tn(e),s=Zo(e)?(e=>E(Xo(e),(e=>C.from(e.element))))(e):r,l=[C.some(On.edge(t))].concat(E(On.positions(r,t),(e=>e.map((e=>e.x))))),a=b(Bt);return E(s,((e,t)=>Yn(e,t,l,a,(e=>{if((e=>{const t=To().browser,o=t.isChromium()||t.isFirefox();return!Un(e)||o})(e))return o(e);{const e=null!=(s=r[t])?h(s):C.none();return Yn(e,t,l,a,(e=>n(C.some(ko(e)))),n)}var s}),n)))},Qn=e=>e.map((e=>e+"px")).getOr(""),Xn=(e,t,o)=>Jn(e,t,Fn,(e=>e.getOrThunk(o.minCellWidth))),Zn=(e,t,o,n,r)=>{const s=nn(e),l=[C.some(o.edge(t))].concat(E(o.positions(s,t),(e=>e.map((e=>e.y)))));return E(s,((e,t)=>Yn(e,t,l,b(zt),n,r)))},er=(e,t)=>()=>et(e)?t(e):parseFloat(Ot(e,"width").getOr("0")),tr=e=>{const t=er(e,(e=>parseFloat(Vn(e)))),o=er(e,ko);return{width:t,pixelWidth:o,getWidths:(t,o)=>((e,t,o)=>Jn(e,t,Pn,(e=>e.fold((()=>o.minCellWidth()),(e=>e/o.pixelWidth()*100)))))(t,e,o),getCellDelta:e=>e/o()*100,singleColumnWidth:(e,t)=>[100-e],minCellWidth:()=>Wt()/o()*100,setElementWidth:Ln,adjustTableWidth:o=>{const n=t();Ln(e,n+o/100*n)},isRelative:!0,label:"percent"}},or=e=>{const t=er(e,ko);return{width:t,pixelWidth:t,getWidths:(t,o)=>Xn(t,e,o),getCellDelta:h,singleColumnWidth:(e,t)=>[Math.max(Wt(),e+t)-e],minCellWidth:Wt,setElementWidth:Wn,adjustTableWidth:o=>{const n=t()+o;Wn(e,n)},isRelative:!1,label:"pixel"}},nr=e=>In(e).fold((()=>(e=>{const t=er(e,ko),o=g(0);return{width:t,pixelWidth:t,getWidths:(t,o)=>Xn(t,e,o),getCellDelta:o,singleColumnWidth:g([0]),minCellWidth:o,setElementWidth:f,adjustTableWidth:f,isRelative:!0,label:"none"}})(e)),(t=>((e,t)=>null!==$n().exec(t)?tr(e):or(e))(e,t))),rr=or,sr=tr,lr=(e,t,o)=>{const n=e[o].element,r=pe.fromTag("td");We(r,pe.fromTag("br")),(t?We:Ae)(n,r)},ar=((e,t)=>{const o=t=>e(t)?C.from(t.dom.nodeValue):C.none();return{get:t=>{if(!e(t))throw new Error("Can only get text value of a text node");return o(t).getOr("")},getOption:o,set:(t,o)=>{if(!e(t))throw new Error("Can only set raw text value of a text node");t.dom.nodeValue=o}}})(re),cr=e=>ar.get(e),ir=e=>ar.getOption(e),mr=(e,t)=>ar.set(e,t),dr=e=>"img"===Z(e)?1:ir(e).fold((()=>Ee(e).length),(e=>e.length)),ur=["img","br"],fr=e=>ir(e).filter((e=>0!==e.trim().length||e.indexOf("\xa0")>-1)).isSome()||D(ur,Z(e)),gr=e=>((e,t)=>{const o=e=>{for(let n=0;npr(e,fr),pr=(e,t)=>{const o=e=>{const n=Ee(e);for(let e=n.length-1;e>=0;e--){const r=n[e];if(t(r))return C.some(r);const s=o(r);if(s.isSome())return s}return C.none()};return o(e)},wr={scope:["row","col"]},br=e=>()=>{const t=pe.fromTag("td",e.dom);return We(t,pe.fromTag("br",e.dom)),t},vr=e=>()=>pe.fromTag("col",e.dom),yr=e=>()=>pe.fromTag("colgroup",e.dom),xr=e=>()=>pe.fromTag("tr",e.dom),Cr=(e,t,o)=>{const n=((e,t)=>{const o=Ve(e,t),n=Ee(qe(e));return Me(o,n),o})(e,t);return G(o,((e,t)=>{null===e?fe(n,t):ie(n,t,e)})),n},Sr=e=>e,Tr=(e,t,o)=>{const n=(e,t)=>{((e,t)=>{const o=e.dom,n=t.dom;xt(o)&&xt(n)&&(n.style.cssText=o.style.cssText)})(e.element,t),kt(t,"height"),1!==e.colspan&&kt(t,"width")};return{col:o=>{const r=pe.fromTag(Z(o.element),t.dom);return n(o,r),e(o.element,r),r},colgroup:yr(t),row:xr(t),cell:r=>{const s=pe.fromTag(Z(r.element),t.dom),l=o.getOr(["strong","em","b","i","span","font","h1","h2","h3","h4","h5","h6","p","div"]),a=l.length>0?((e,t,o)=>gr(e).map((n=>{const r=o.join(","),s=nt(n,r,(t=>ye(t,e)));return A(s,((e,t)=>{const o=He(t);return fe(o,"contenteditable"),We(e,o),o}),t)})).getOr(t))(r.element,s,l):s;return We(a,pe.fromTag("br")),n(r,s),((e,t)=>{G(wr,((o,n)=>ue(e,n).filter((e=>D(o,e))).each((e=>ie(t,n,e)))))})(r.element,s),e(r.element,s),s},replace:Cr,colGap:vr(t),gap:br(t)}},Rr=e=>({col:vr(e),colgroup:yr(e),row:xr(e),cell:br(e),replace:Sr,colGap:vr(e),gap:br(e)}),Dr=e=>pe.fromDom(e.getBody()),Or=e=>t=>ye(t,Dr(e)),kr=e=>{fe(e,"data-mce-style");const t=e=>fe(e,"data-mce-style");N(It(e),t),N(Pt(e),t),N(Ht(e),t)},Er=e=>pe.fromDom(e.selection.getStart()),Nr=e=>e.getBoundingClientRect().width,Br=e=>e.getBoundingClientRect().height,zr=(e,t)=>{const o=t.column,n=t.column+t.colspan-1,r=t.row,s=t.row+t.rowspan-1;return o<=e.finishCol&&n>=e.startCol&&r<=e.finishRow&&s>=e.startRow},Ar=(e,t)=>t.column>=e.startCol&&t.column+t.colspan-1<=e.finishCol&&t.row>=e.startRow&&t.row+t.rowspan-1<=e.finishRow,Wr=(e,t,o)=>{const n=Yo(e,t,ye),r=Yo(e,o,ye);return n.bind((e=>r.map((t=>{return o=e,n=t,{startRow:Math.min(o.row,n.row),startCol:Math.min(o.column,n.column),finishRow:Math.max(o.row+o.rowspan-1,n.row+n.rowspan-1),finishCol:Math.max(o.column+o.colspan-1,n.column+n.colspan-1)};var o,n}))))},Lr=(e,t,o)=>Wr(e,t,o).map((t=>{const o=Jo(e,w(zr,t));return E(o,(e=>e.element))})),_r=(e,t)=>Yo(e,t,((e,t)=>xe(t,e))).map((e=>e.element)),Mr=(e,t,o)=>{const n=Ir(e);return Lr(n,t,o)},jr=(e,t,o,n,r)=>{const s=Ir(e),l=ye(e,o)?C.some(t):_r(s,t),a=ye(e,r)?C.some(n):_r(s,n);return l.bind((e=>a.bind((t=>Lr(s,e,t)))))},Ir=Uo;var Pr=["body","p","div","article","aside","figcaption","figure","footer","header","nav","section","ol","ul","li","table","thead","tbody","tfoot","caption","tr","td","th","h1","h2","h3","h4","h5","h6","blockquote","pre","address"],Fr=()=>({up:g({selector:ct,closest:dt,predicate:at,all:De}),down:g({selector:st,predicate:ot}),styles:g({get:Rt,getRaw:Ot,set:St,remove:kt}),attrs:g({get:de,set:ie,remove:fe,copyTo:(e,t)=>{const o=ge(e);me(t,o)}}),insert:g({before:Be,after:ze,afterAll:_e,append:We,appendAll:Me,prepend:Ae,wrap:Le}),remove:g({unwrap:Pe,remove:Ie}),create:g({nu:pe.fromTag,clone:e=>pe.fromDom(e.dom.cloneNode(!1)),text:pe.fromText}),query:g({comparePosition:(e,t)=>e.dom.compareDocumentPosition(t.dom),prevSibling:Oe,nextSibling:ke}),property:g({children:Ee,name:Z,parent:Re,document:e=>Te(e).dom,isText:re,isComment:oe,isElement:ne,isSpecial:e=>{const t=Z(e);return D(["script","noscript","iframe","noframes","noembed","title","style","textarea","xmp"],t)},getLanguage:e=>ne(e)?ue(e,"lang"):C.none(),getText:cr,setText:mr,isBoundary:e=>!!ne(e)&&("body"===Z(e)||D(Pr,Z(e))),isEmptyTag:e=>!!ne(e)&&D(["br","img","hr","input"],Z(e)),isNonEditable:e=>ne(e)&&"false"===de(e,"contenteditable")}),eq:ye,is:Ce});const Hr=(e,t,o,n)=>{const r=t(e,o);return A(n,((o,n)=>{const r=t(e,n);return qr(e,o,r)}),r)},qr=(e,t,o)=>t.bind((t=>o.filter(w(e.eq,t)))),Vr=Fr(),$r=(e,t)=>((e,t,o)=>o.length>0?((e,t,o,n)=>n(e,t,o[0],o.slice(1)))(e,t,o,Hr):C.none())(Vr,((t,o)=>e(o)),t),Ur=e=>ct(e,"table"),Gr=(e,t,o)=>{const n=e=>t=>void 0!==o&&o(t)||ye(t,e);return ye(e,t)?C.some({boxes:C.some([e]),start:e,finish:t}):Ur(e).bind((r=>Ur(t).bind((s=>{if(ye(r,s))return C.some({boxes:Mr(r,e,t),start:e,finish:t});if(xe(r,s)){const o=nt(t,"td,th",n(r)),l=o.length>0?o[o.length-1]:t;return C.some({boxes:jr(r,e,r,t,s),start:e,finish:l})}if(xe(s,r)){const o=nt(e,"td,th",n(s)),l=o.length>0?o[o.length-1]:e;return C.some({boxes:jr(s,e,r,t,s),start:e,finish:l})}return((e,t,o)=>((e,t,o,n=y)=>{const r=[t].concat(e.up().all(t)),s=[o].concat(e.up().all(o)),l=e=>_(e,n).fold((()=>e),(t=>e.slice(0,t+1))),a=l(r),c=l(s),i=L(a,(t=>O(c,((e,t)=>w(e.eq,t))(e,t))));return{firstpath:a,secondpath:c,shared:i}})(Vr,e,t,void 0))(e,t).shared.bind((l=>dt(l,"table",o).bind((o=>{const l=nt(t,"td,th",n(o)),a=l.length>0?l[l.length-1]:t,c=nt(e,"td,th",n(o)),i=c.length>0?c[c.length-1]:e;return C.some({boxes:jr(o,e,r,t,s),start:i,finish:a})}))))}))))},Kr=(e,t)=>{const o=st(e,t);return o.length>0?C.some(o):C.none()},Yr=(e,t,o)=>mt(e,t).bind((t=>mt(e,o).bind((e=>$r(Ur,[t,e]).map((o=>({first:t,last:e,table:o}))))))),Jr=(e,t,o,n,r)=>((e,t)=>L(e,(e=>we(e,t))))(e,r).bind((e=>((e,t,o)=>Ft(e).bind((n=>((e,t,o,n)=>Yo(e,t,ye).bind((t=>{const r=o>0?t.row+t.rowspan-1:t.row,s=n>0?t.column+t.colspan-1:t.column;return Ko(e,r+o,s+n).map((e=>e.element))})))(Ir(n),e,t,o))))(e,t,o).bind((e=>((e,t)=>ct(e,"table").bind((o=>mt(o,t).bind((t=>Gr(t,e).bind((e=>e.boxes.map((t=>({boxes:t,start:e.start,finish:e.finish}))))))))))(e,n))))),Qr=(e,t)=>Kr(e,t),Xr=(e,t,o)=>Yr(e,t,o).bind((t=>{const o=t=>ye(e,t),n="thead,tfoot,tbody,table",r=ct(t.first,n,o),s=ct(t.last,n,o);return r.bind((e=>s.bind((o=>ye(e,o)?((e,t,o)=>((e,t,o)=>Wr(e,t,o).bind((t=>((e,t)=>{let o=!0;const n=w(Ar,t);for(let r=t.startRow;r<=t.finishRow;r++)for(let s=t.startCol;s<=t.finishCol;s++)o=o&&Ko(e,r,s).exists(n);return o?C.some(t):C.none()})(e,t))))(Ir(e),t,o))(t.table,t.first,t.last):C.none()))))})),Zr=h,es=e=>{const t=(e,t)=>ue(e,t).exists((e=>parseInt(e,10)>1));return e.length>0&&I(e,(e=>t(e,"rowspan")||t(e,"colspan")))?C.some(e):C.none()},ts=(e,t,o)=>t.length<=1?C.none():Xr(e,o.firstSelectedSelector,o.lastSelectedSelector).map((e=>({bounds:e,cells:t}))),os={selected:"data-mce-selected",selectedSelector:"td[data-mce-selected],th[data-mce-selected]",firstSelected:"data-mce-first-selected",firstSelectedSelector:"td[data-mce-first-selected],th[data-mce-first-selected]",lastSelected:"data-mce-last-selected",lastSelectedSelector:"td[data-mce-last-selected],th[data-mce-last-selected]"},ns=(e,t,o)=>({element:o,mergable:ts(t,e,os),unmergable:es(e),selection:Zr(e)}),rs=e=>(t,o)=>{const n=Z(t),r="col"===n||"colgroup"===n?Ft(s=t).bind((e=>Qr(e,os.firstSelectedSelector))).fold(g(s),(e=>e[0])):t;var s;return dt(r,e,o)},ss=rs("th,td,caption"),ls=rs("th,td"),as=e=>{return t=e.model.table.getSelectedCells(),E(t,pe.fromDom);var t},cs=(e,t)=>{e.on("BeforeGetContent",(t=>{const o=o=>{t.preventDefault(),(e=>Ft(e[0]).map((e=>{const t=((e,t)=>{const o=e=>we(e.element,t),n=qe(e),r=Ut(n),s=nr(e),l=Go(r),a=((e,t)=>{const o=e.grid.columns;let n=e.grid.rows,r=o,s=0,l=0;const a=[],c=[];return G(e.access,(e=>{if(a.push(e),t(e)){c.push(e);const t=e.row,o=t+e.rowspan-1,a=e.column,i=a+e.colspan-1;ts&&(s=o),al&&(l=i)}})),((e,t,o,n,r,s)=>({minRow:e,minCol:t,maxRow:o,maxCol:n,allCells:r,selectedCells:s}))(n,r,s,l,a,c)})(l,o),c="th:not("+t+"),td:not("+t+")",i=Mt(n,"th,td",(e=>we(e,c)));N(i,Ie),((e,t,o,n)=>{const r=z(e,(e=>"colgroup"!==e.section)),s=t.grid.columns,l=t.grid.rows;for(let e=0;eo.maxRow||ao.maxCol||(Ko(t,e,a).filter(n).isNone()?lr(r,l,e):l=!0)}})(r,l,a,o);const m=((e,t,o,n)=>{if(0===n.minCol&&t.grid.columns===n.maxCol+1)return 0;const r=Xn(t,e,o),s=W(r,((e,t)=>e+t),0),l=W(r.slice(n.minCol,n.maxCol+1),((e,t)=>e+t),0),a=l/s*o.pixelWidth()-o.pixelWidth();return o.getCellDelta(a)})(e,Uo(e),s,a);return((e,t,o,n)=>{G(o.columns,(e=>{(e.columnt.maxCol)&&Ie(e.element)}));const r=z(_t(e,"tr"),(e=>0===e.dom.childElementCount));N(r,Ie),t.minCol!==t.maxCol&&t.minRow!==t.maxRow||N(_t(e,"th,td"),(e=>{fe(e,"rowspan"),fe(e,"colspan")})),fe(e,Po),fe(e,"data-snooker-col-series"),nr(e).adjustTableWidth(n)})(n,a,l,m),n})(e,"[data-mce-selected]");return kr(t),[t]})))(o).each((o=>{t.content="text"===t.format?(e=>E(e,(e=>e.dom.innerText)).join(""))(o):((e,t)=>E(t,(t=>e.selection.serializer.serialize(t.dom,{}))).join(""))(e,o)}))};if(!0===t.selection){const t=(e=>z(as(e),(e=>we(e,os.selectedSelector))))(e);t.length>=1&&o(t)}})),e.on("BeforeSetContent",(o=>{if(!0===o.selection&&!0===o.paste){const n=as(e);H(n).each((n=>{Ft(n).each((r=>{const s=z(((e,t)=>{const o=document.createElement("div");return o.innerHTML=e,Ee(pe.fromDom(o))})(o.content),(e=>"meta"!==Z(e))),l=ae("table");if(1===s.length&&l(s[0])){o.preventDefault();const l=pe.fromDom(e.getDoc()),a=Rr(l),c=((e,t,o)=>({element:e,clipboard:t,generators:o}))(n,s[0],a);t.pasteCells(r,c).each((()=>{e.focus()}))}}))}))}}))},is=(e,t)=>({element:e,offset:t}),ms=(e,t,o)=>e.property().isText(t)&&0===e.property().getText(t).trim().length||e.property().isComment(t)?o(t).bind((t=>ms(e,t,o).orThunk((()=>C.some(t))))):C.none(),ds=(e,t)=>e.property().isText(t)?e.property().getText(t).length:e.property().children(t).length,us=(e,t)=>{const o=ms(e,t,e.query().prevSibling).getOr(t);if(e.property().isText(o))return is(o,ds(e,o));const n=e.property().children(o);return n.length>0?us(e,n[n.length-1]):is(o,ds(e,o))},fs=us,gs=Fr(),hs=(e,t)=>{if(!Bt(e)){const o=(e=>In(e).bind((e=>{return t=e,o=["fixed","relative","empty"],C.from(En.exec(t)).bind((e=>{const t=Number(e[1]),n=e[2];return((e,t)=>O(t,(t=>O(kn[t],(t=>e===t)))))(n,o)?C.some({value:t,unit:n}):C.none()}));var t,o})))(e);o.each((o=>{const n=o.value/2;qn(e,n,o.unit),qn(t,n,o.unit)}))}},ps=e=>E(e,g(0)),ws=(e,t,o,n,r)=>r(e.slice(0,t)).concat(n).concat(r(e.slice(o))),bs=e=>(t,o,n,r)=>{if(e(n)){const e=Math.max(r,t[o]-Math.abs(n)),s=Math.abs(e-t[o]);return n>=0?s:-s}return n},vs=bs((e=>e<0)),ys=bs(x),xs=()=>{const e=(e,t,o,n)=>{const r=(100+o)/100,s=Math.max(n,(e[t]+o)/r);return E(e,((e,o)=>(o===t?s:e/r)-e))},t=(t,o,n,r,s,l)=>l?e(t,o,r,s):((e,t,o,n,r)=>{const s=vs(e,t,n,r);return ws(e,t,o+1,[s,0],ps)})(t,o,n,r,s);return{resizeTable:(e,t)=>e(t),clampTableDelta:vs,calcLeftEdgeDeltas:t,calcMiddleDeltas:(e,o,n,r,s,l,a)=>t(e,n,r,s,l,a),calcRightEdgeDeltas:(t,o,n,r,s,l)=>{if(l)return e(t,n,r,s);{const e=vs(t,n,r,s);return ps(t.slice(0,n)).concat([e])}},calcRedestributedWidths:(e,t,o,n)=>{if(n){const n=(t+o)/t,r=E(e,(e=>e/n));return{delta:100*n-100,newSizes:r}}return{delta:o,newSizes:e}}}},Cs=()=>{const e=(e,t,o,n,r)=>{const s=ys(e,n>=0?o:t,n,r);return ws(e,t,o+1,[s,-s],ps)};return{resizeTable:(e,t,o)=>{o&&e(t)},clampTableDelta:(e,t,o,n,r)=>{if(r){if(o>=0)return o;{const t=W(e,((e,t)=>e+t-n),0);return Math.max(-t,o)}}return vs(e,t,o,n)},calcLeftEdgeDeltas:e,calcMiddleDeltas:(t,o,n,r,s,l)=>e(t,n,r,s,l),calcRightEdgeDeltas:(e,t,o,n,r,s)=>{if(s)return ps(e);{const t=n/e.length;return E(e,g(t))}},calcRedestributedWidths:(e,t,o,n)=>({delta:0,newSizes:e})}},Ss=e=>Uo(e).grid,Ts=ae("th"),Rs=e=>I(e,(e=>Ts(e.element))),Ds=(e,t)=>e&&t?"sectionCells":e?"section":"cells",Os=e=>{const t="thead"===e.section,o=ut(ks(e.cells),"th");return"tfoot"===e.section?{type:"footer"}:t||o?{type:"header",subType:Ds(t,o)}:{type:"body"}},ks=e=>{const t=z(e,(e=>Ts(e.element)));return 0===t.length?C.some("td"):t.length===e.length?C.some("th"):C.none()},Es=(e,t,o)=>Ke(o(e.element,t),!0,e.isLocked),Ns=(e,t)=>e.section!==t?Ye(e.element,e.cells,t,e.isNew):e,Bs=()=>({transformRow:Ns,transformCell:(e,t,o)=>{const n=o(e.element,t),r="td"!==Z(n)?((e,t)=>{const o=Ve(e,"td");ze(e,o);const n=Ee(e);return Me(o,n),Ie(e),o})(n):n;return Ke(r,e.isNew,e.isLocked)}}),zs=()=>({transformRow:Ns,transformCell:Es}),As=()=>({transformRow:(e,t)=>Ns(e,"thead"===t?"tbody":t),transformCell:Es}),Ws=Bs,Ls=zs,_s=As,Ms=()=>({transformRow:h,transformCell:Es}),js=e=>dt(e,"[contenteditable]"),Is=(e,t=!1)=>et(e)?e.dom.isContentEditable:js(e).fold(g(t),(e=>"true"===Ps(e))),Ps=e=>e.dom.contentEditable,Fs=(e,t,o,n)=>{o===n?fe(e,t):ie(e,t,o)},Hs=(e,t,o)=>{q(rt(e,t)).fold((()=>Ae(e,o)),(e=>ze(e,o)))},qs=(e,t)=>{const o=[],n=[],r=e=>E(e,(e=>{e.isNew&&o.push(e.element);const t=e.element;return je(t),N(e.cells,(e=>{e.isNew&&n.push(e.element),Fs(e.element,"colspan",e.colspan,1),Fs(e.element,"rowspan",e.rowspan,1),We(t,e.element)})),t})),s=e=>j(e,(e=>E(e.cells,(e=>(Fs(e.element,"span",e.colspan,1),e.element))))),l=(t,o)=>{const n=((e,t)=>{const o=it(e,t).getOrThunk((()=>{const o=pe.fromTag(t,Se(e).dom);return"thead"===t?Hs(e,"caption,colgroup",o):"colgroup"===t?Hs(e,"caption",o):We(e,o),o}));return je(o),o})(e,o),l=("colgroup"===o?s:r)(t);Me(n,l)},a=(t,o)=>{t.length>0?l(t,o):(t=>{it(e,t).each(Ie)})(o)},c=[],i=[],m=[],d=[];return N(t,(e=>{switch(e.section){case"thead":c.push(e);break;case"tbody":i.push(e);break;case"tfoot":m.push(e);break;case"colgroup":d.push(e)}})),a(d,"colgroup"),a(c,"thead"),a(i,"tbody"),a(m,"tfoot"),{newRows:o,newCells:n}},Vs=(e,t)=>{if(0===e.length)return 0;const o=e[0];return _(e,(e=>!t(o.element,e.element))).getOr(e.length)},$s=(e,t)=>{const o=E(e,(e=>E(e.cells,y)));return E(e,((n,r)=>{const s=j(n.cells,((n,s)=>{if(!1===o[r][s]){const m=((e,t,o,n)=>{const r=((e,t)=>e[t])(e,t),s="colgroup"===r.section,l=Vs(r.cells.slice(o),n),a=s?1:Vs(((e,t)=>E(e,(e=>Lo(e,t))))(e.slice(t),o),n);return{colspan:l,rowspan:a}})(e,r,s,t);return((e,t,n,r)=>{for(let s=e;s({element:e,cells:t,section:o,isNew:n}))(n.element,s,n.section,n.isNew)}))},Us=(e,t,o)=>{const n=[];N(e.colgroups,(r=>{const s=[];for(let n=0;nKe(e.element,o,!1))).getOrThunk((()=>Ke(t.colGap(),!0,!1)));s.push(r)}n.push(Ye(r.element,s,"colgroup",o))}));for(let r=0;rKe(e.element,o,e.isLocked))).getOrThunk((()=>Ke(t.gap(),!0,!1)));s.push(l)}const l=e.all[r],a=Ye(l.element,s,l.section,o);n.push(a)}return n},Gs=e=>$s(e,ye),Ks=(e,t)=>V(e.all,(e=>L(e.cells,(e=>ye(t,e.element))))),Ys=(e,t,o)=>{const n=E(t.selection,(t=>jt(t).bind((t=>Ks(e,t))).filter(o))),r=ft(n);return gt(r.length>0,r)},Js=(e,t,o,n,r)=>(s,l,a,c)=>{const i=Uo(s),m=C.from(null==c?void 0:c.section).getOrThunk(Ms);return t(i,l).map((t=>{const o=((e,t)=>Us(e,t,!1))(i,a),n=e(o,t,ye,r(a),m),s=Ho(n.grid);return{info:t,grid:Gs(n.grid),cursor:n.cursor,lockedColumns:s}})).bind((e=>{const t=qs(s,e.grid),r=C.from(null==c?void 0:c.sizing).getOrThunk((()=>nr(s))),l=C.from(null==c?void 0:c.resize).getOrThunk(Cs);return o(s,e.grid,e.info,{sizing:r,resize:l,section:m}),n(s),fe(s,Po),e.lockedColumns.length>0&&ie(s,Po,e.lockedColumns.join(",")),C.some({cursor:e.cursor,newRows:t.newRows,newCells:t.newCells})}))},Qs=(e,t)=>Ys(e,t,x).map((e=>({cells:e,generators:t.generators,clipboard:t.clipboard}))),Xs=(e,t)=>Ys(e,t,x),Zs=(e,t)=>Ys(e,t,(e=>!e.isLocked)),el=(e,t)=>I(t,(t=>((e,t)=>Ks(e,t).exists((e=>!e.isLocked)))(e,t))),tl=(e,t,o,n)=>{const r=jo(e).rows;let s=!0;for(let e=0;e{const t=t=>t(e),o=g(e),n=()=>r,r={tag:!0,inner:e,fold:(t,o)=>o(e),isValue:x,isError:y,map:t=>rl.value(t(e)),mapError:n,bind:t,exists:t,forall:t,getOr:o,or:n,getOrThunk:o,orThunk:n,getOrDie:o,each:t=>{t(e)},toOptional:()=>C.some(e)};return r},nl=e=>{const t=()=>o,o={tag:!1,inner:e,fold:(t,o)=>t(e),isValue:y,isError:x,map:t,mapError:t=>rl.error(t(e)),bind:t,exists:y,forall:x,getOr:h,or:h,getOrThunk:v,orThunk:v,getOrDie:(n=String(e),()=>{throw new Error(n)}),each:f,toOptional:C.none};var n;return o},rl={value:ol,error:nl,fromOption:(e,t)=>e.fold((()=>nl(t)),ol)},sl=(e,t)=>({rowDelta:0,colDelta:Mo(e[0])-Mo(t[0])}),ll=(e,t)=>({rowDelta:e.length-t.length,colDelta:0}),al=(e,t,o,n)=>{const r="colgroup"===t.section?o.col:o.cell;return k(e,(e=>Ke(r(),!0,n(e))))},cl=(e,t,o,n)=>{const r=e[e.length-1];return e.concat(k(t,(()=>{const e="colgroup"===r.section?o.colgroup:o.row,t=Io(r,e,h),s=al(t.cells.length,t,o,(e=>X(n,e.toString())));return Wo(t,s)})))},il=(e,t,o,n)=>E(e,(e=>{const r=al(t,e,o,y);return Bo(e,n,r)})),ml=(e,t,o)=>{const n=t.colDelta<0?il:h,r=t.rowDelta<0?cl:h,s=Ho(e),l=Mo(e[0]),a=O(s,(e=>e===l-1)),c=n(e,Math.abs(t.colDelta),o,a?l-1:l),i=Ho(c);return r(c,Math.abs(t.rowDelta),o,P(i,x))},dl=(e,t,o,n)=>{const r=w(n,Lo(e[t],o).element),s=e[t];return e.length>1&&Mo(s)>1&&(o>0&&r(_o(s,o-1))||o0&&r(_o(e[t-1],o))||tz(o,(o=>o>=e.column&&o<=Mo(t[0])+e.column)),fl=(e,t,o,n,r)=>{((e,t,o,n)=>{t>0&&t{const r=e.cells[t-1];let s=0;const l=n();for(;e.cells.length>t+s&&o(r.element,e.cells[t+s].element);)Ao(e,t+s,Ke(l,!0,e.cells[t+s].isLocked)),s++}))})(t,e,r,n.cell);const s=ll(o,t),l=ml(o,s,n),a=ll(t,l),c=ml(t,a,n);return E(c,((t,o)=>Bo(t,e,l[o].cells)))},gl=(e,t,o,n,r)=>{((e,t,o,n)=>{const r=jo(e).rows;if(t>0&&tW(e,((e,o)=>O(e,(e=>t(e.element,o.element)))?e:e.concat([o])),[]))(r[t-1].cells,o);N(e,(e=>{let s=C.none();for(let l=t;l{Ao(a,t,Ke(e,!0,c.isLocked))})))}}))}})(t,e,r,n.cell);const s=Ho(t),l=sl(t,o),a={...l,colDelta:l.colDelta-s.length},c=ml(t,a,n),{cols:i,rows:m}=jo(c),d=Ho(c),u=sl(o,t),f={...u,colDelta:u.colDelta+d.length},g=(p=n,w=d,E(o,(e=>W(w,((t,o)=>{const n=al(1,e,p,x)[0];return zo(t,o,n)}),e)))),h=ml(g,f,n);var p,w;return[...i,...m.slice(0,e),...h,...m.slice(e,m.length)]},hl=(e,t,o,n,r)=>{const{rows:s,cols:l}=jo(e),a=s.slice(0,t),c=s.slice(t);return[...l,...a,((e,t,o,n)=>Io(e,(e=>n(e,o)),t))(s[o],((e,o)=>t>0&&tE(e,(e=>{const s=t>0&&t{if("colgroup"!==o&&n)return Lo(e,t);{const t=Lo(e,r);return Ke(l(t.element,s),!0,!1)}})(e,t,e.section,s,o,n,r);return zo(e,t,l)})),wl=(e,t,o,n)=>((e,t,o,n)=>void 0!==_o(e[t],o)&&t>0&&n(_o(e[t-1],o),_o(e[t],o)))(e,t,o,n)||((e,t,o)=>t>0&&o(_o(e,t-1),_o(e,t)))(e[t],o,n),bl=(e,t,o,n)=>{const r=e=>(e=>"row"===e?zt(t):Bt(t))(e)?`${e}group`:e;return e?Ts(t)?r(o):null:n&&Ts(t)?r("row"===o?"col":"row"):null},vl=(e,t,o)=>Ke(o(e.element,t),!0,e.isLocked),yl=(e,t,o,n,r,s,l)=>E(e,((e,a)=>((e,c)=>{const i=e.cells,m=E(i,((e,c)=>{if((e=>O(t,(t=>o(e.element,t.element))))(e)){const t=l(e,a,c)?r(e,o,n):e;return s(t,a,c).each((e=>{var o,n;o=t.element,n={scope:C.from(e)},G(n,((e,t)=>{e.fold((()=>{fe(o,t)}),(e=>{ce(o.dom,t,e)}))}))})),t}return e}));return Ye(e.element,m,e.section,e.isNew)})(e))),xl=(e,t,o)=>j(e,((n,r)=>wl(e,r,t,o)?[]:[Lo(n,t)])),Cl=(e,t,o,n,r)=>{const s=jo(e).rows,l=j(t,(e=>xl(s,e,n))),a=E(s,(e=>Rs(e.cells))),c=((e,t)=>I(t,h)&&Rs(e)?x:(e,o,n)=>!("th"===Z(e.element)&&t[o]))(l,a),i=((e,t)=>(o,n)=>C.some(bl(e,o.element,"row",t[n])))(o,a);return yl(e,l,n,r,vl,i,c)},Sl=(e,t,o,n)=>{const r=jo(e).rows,s=E(t,(e=>Lo(r[e.row],e.column)));return yl(e,s,o,n,vl,C.none,x)},Tl=e=>{if(!l(e))throw new Error("cases must be an array");if(0===e.length)throw new Error("there must be at least one case");const t=[],o={};return N(e,((n,r)=>{const s=$(n);if(1!==s.length)throw new Error("one and only one name per case");const a=s[0],c=n[a];if(void 0!==o[a])throw new Error("duplicate key detected:"+a);if("cata"===a)throw new Error("cannot have a case named cata (sorry)");if(!l(c))throw new Error("case arguments must be an array");t.push(a),o[a]=(...o)=>{const n=o.length;if(n!==c.length)throw new Error("Wrong number of arguments to case "+a+". Expected "+c.length+" ("+c+"), got "+n);return{fold:(...t)=>{if(t.length!==e.length)throw new Error("Wrong number of arguments to fold. Expected "+e.length+", got "+t.length);return t[r].apply(null,o)},match:e=>{const n=$(e);if(t.length!==n.length)throw new Error("Wrong number of arguments to match. Expected: "+t.join(",")+"\nActual: "+n.join(","));if(!I(t,(e=>D(n,e))))throw new Error("Not all branches were specified when using match. Specified: "+n.join(", ")+"\nRequired: "+t.join(", "));return e[a].apply(null,o)},log:e=>{console.log(e,{constructors:t,constructor:a,params:o})}}}})),o},Rl={...Tl([{none:[]},{only:["index"]},{left:["index","next"]},{middle:["prev","index","next"]},{right:["prev","index"]}])},Dl=(e,t,o)=>{let n=0;for(let r=e;r{const o=Qo(e);return E(o,(e=>{const o=Dl(e.row,e.row+e.rowspan,t);return{element:e.element,height:o,rowspan:e.rowspan}}))},kl=(e,t,o)=>{const n=((e,t)=>Zo(e)?((e,t)=>{const o=Xo(e);return E(o,((e,o)=>({element:e.element,width:t[o],colspan:e.colspan})))})(e,t):((e,t)=>{const o=Qo(e);return E(o,(e=>{const o=Dl(e.column,e.column+e.colspan,t);return{element:e.element,width:o,colspan:e.colspan}}))})(e,t))(e,t);N(n,(e=>{o.setElementWidth(e.element,e.width)}))},El=(e,t,o,n,r)=>{const s=Uo(e),l=r.getCellDelta(t),a=r.getWidths(s,r),c=o===s.grid.columns-1,i=n.clampTableDelta(a,o,l,r.minCellWidth(),c),m=((e,t,o,n,r)=>{const s=e.slice(0),l=((e,t)=>0===e.length?Rl.none():1===e.length?Rl.only(0):0===t?Rl.left(0,1):t===e.length-1?Rl.right(t-1,t):t>0&&tn.singleColumnWidth(s[e],o)),((e,t)=>r.calcLeftEdgeDeltas(s,e,t,o,n.minCellWidth(),n.isRelative)),((e,t,l)=>r.calcMiddleDeltas(s,e,t,l,o,n.minCellWidth(),n.isRelative)),((e,t)=>r.calcRightEdgeDeltas(s,e,t,o,n.minCellWidth(),n.isRelative)))})(a,o,i,r,n),d=E(m,((e,t)=>e+a[t]));kl(s,d,r),n.resizeTable(r.adjustTableWidth,i,c)},Nl=e=>W(e,((e,t)=>O(e,(e=>e.column===t.column))?e:e.concat([t])),[]).sort(((e,t)=>e.column-t.column)),Bl=ae("col"),zl=ae("colgroup"),Al=e=>"tr"===Z(e)||zl(e),Wl=e=>({element:e,colspan:Et(e,"colspan",1),rowspan:Et(e,"rowspan",1)}),Ll=e=>ue(e,"scope").map((e=>e.substr(0,3))),_l=(e,t=Wl)=>{const o=o=>{if(Al(o))return zl((r={element:o}).element)?e.colgroup(r):e.row(r);{const r=o,s=(t=>Bl(t.element)?e.col(t):e.cell(t))(t(r));return n=C.some({item:r,replacement:s}),s}var r};let n=C.none();return{getOrInit:(e,t)=>n.fold((()=>o(e)),(n=>t(e,n.item)?n.replacement:o(e)))}},Ml=e=>t=>{const o=[],n=n=>{const r="td"===e?{scope:null}:{},s=t.replace(n,e,r);return o.push({item:n,sub:s}),s};return{replaceOrInit:(e,t)=>{if(Al(e)||Bl(e))return e;{const r=e;return((e,t)=>L(o,(o=>t(o.item,e))))(r,t).fold((()=>n(r)),(o=>t(e,o.item)?o.sub:n(r)))}}}},jl=e=>({unmerge:t=>{const o=Ll(t);return o.each((e=>ie(t,"scope",e))),()=>{const n=e.cell({element:t,colspan:1,rowspan:1});return kt(n,"width"),kt(t,"width"),o.each((e=>ie(n,"scope",e))),n}},merge:e=>(kt(e[0],"width"),(()=>{const t=ft(E(e,Ll));if(0===t.length)return C.none();{const e=t[0],o=["row","col"];return O(t,(t=>t!==e&&D(o,t)))?C.none():C.from(e)}})().fold((()=>fe(e[0],"scope")),(t=>ie(e[0],"scope",t+"group"))),g(e[0]))}),Il=["body","p","div","article","aside","figcaption","figure","footer","header","nav","section","ol","ul","table","thead","tfoot","tbody","caption","tr","td","th","h1","h2","h3","h4","h5","h6","blockquote","pre","address"],Pl=Fr(),Fl=e=>((e,t)=>{const o=e.property().name(t);return D(Il,o)})(Pl,e),Hl=e=>((e,t)=>{const o=e.property().name(t);return D(["ol","ul"],o)})(Pl,e),ql=e=>{const t=ae("br"),o=e=>hr(e).bind((o=>{const n=ke(o).map((e=>!!Fl(e)||!!((e,t)=>D(["br","img","hr","input"],e.property().name(t)))(Pl,e)&&"img"!==Z(e))).getOr(!1);return Re(o).map((r=>{return!0===n||("li"===Z(s=r)||at(s,Hl).isSome())||t(o)||Fl(r)&&!ye(e,r)?[]:[pe.fromTag("br")];var s}))})).getOr([]),n=(()=>{const n=j(e,(e=>{const n=Ee(e);return(e=>I(e,(e=>t(e)||re(e)&&0===cr(e).trim().length)))(n)?[]:n.concat(o(e))}));return 0===n.length?[pe.fromTag("br")]:n})();je(e[0]),Me(e[0],n)},Vl=e=>Is(e,!0),$l=e=>{0===It(e).length&&Ie(e)},Ul=(e,t)=>({grid:e,cursor:t}),Gl=(e,t,o)=>{const n=((e,t,o)=>{var n,r;const s=jo(e).rows;return C.from(null===(r=null===(n=s[t])||void 0===n?void 0:n.cells[o])||void 0===r?void 0:r.element).filter(Vl).orThunk((()=>(e=>V(e,(e=>V(e.cells,(e=>{const t=e.element;return gt(Vl(t),t)})))))(s)))})(e,t,o);return Ul(e,n)},Kl=e=>W(e,((e,t)=>O(e,(e=>e.row===t.row))?e:e.concat([t])),[]).sort(((e,t)=>e.row-t.row)),Yl=(e,t)=>(o,n,r,s,l)=>{const a=Kl(n),c=E(a,(e=>e.row)),i=((e,t,o,n,r,s,l)=>{const{cols:a,rows:c}=jo(e),i=c[t[0]],m=j(t,(e=>((e,t,o)=>{const n=e[t];return j(n.cells,((n,r)=>wl(e,t,r,o)?[]:[n]))})(c,e,r))),d=E(i.cells,((e,t)=>Rs(xl(c,t,r)))),u=[...c];N(t,(e=>{u[e]=l.transformRow(c[e],o)}));const f=[...a,...u],g=((e,t)=>I(t,h)&&Rs(e.cells)?x:(e,o,n)=>!("th"===Z(e.element)&&t[n]))(i,d),p=((e,t)=>(o,n,r)=>C.some(bl(e,o.element,"col",t[r])))(n,d);return yl(f,m,r,s,l.transformCell,p,g)})(o,c,e,t,r,s.replaceOrInit,l);return Gl(i,n[0].row,n[0].column)},Jl=Yl("thead",!0),Ql=Yl("tbody",!1),Xl=Yl("tfoot",!1),Zl=(e,t,o)=>{const n=((e,t)=>Vt(e,(()=>t)))(e,o.section),r=Go(n);return Us(r,t,!0)},ea=(e,t,o,n)=>((e,t,o,n)=>{const r=Go(t),s=n.getWidths(r,n);kl(r,s,n)})(0,t,0,n.sizing),ta=(e,t,o,n)=>((e,t,o,n,r)=>{const s=Go(t),l=n.getWidths(s,n),a=n.pixelWidth(),{newSizes:c,delta:i}=r.calcRedestributedWidths(l,a,o.pixelDelta,n.isRelative);kl(s,c,n),n.adjustTableWidth(i)})(0,t,o,n.sizing,n.resize),oa=(e,t)=>O(t,(e=>0===e.column&&e.isLocked)),na=(e,t)=>O(t,(t=>t.column+t.colspan>=e.grid.columns&&t.isLocked)),ra=(e,t)=>{const o=tn(e),n=Nl(t);return W(n,((e,t)=>e+o[t.column].map(Eo).getOr(0)),0)},sa=e=>(t,o)=>Xs(t,o).filter((o=>!(e?oa:na)(t,o))).map((e=>({details:e,pixelDelta:ra(t,e)}))),la=e=>(t,o)=>Qs(t,o).filter((o=>!(e?oa:na)(t,o.cells))),aa=Ml("th"),ca=Ml("td"),ia=Js(((e,t,o,n)=>{const r=t[0].row,s=Kl(t),l=A(s,((e,t)=>({grid:hl(e.grid,r,t.row+e.delta,o,n.getOrInit),delta:e.delta+1})),{grid:e,delta:0}).grid;return Gl(l,r,t[0].column)}),Xs,f,f,_l),ma=Js(((e,t,o,n)=>{const r=Kl(t),s=r[r.length-1],l=s.row+s.rowspan,a=A(r,((e,t)=>hl(e,l,t.row,o,n.getOrInit)),e);return Gl(a,l,t[0].column)}),Xs,f,f,_l),da=Js(((e,t,o,n)=>{const r=t.details,s=Nl(r),l=s[0].column,a=A(s,((e,t)=>({grid:pl(e.grid,l,t.column+e.delta,o,n.getOrInit),delta:e.delta+1})),{grid:e,delta:0}).grid;return Gl(a,r[0].row,l)}),sa(!0),ta,f,_l),ua=Js(((e,t,o,n)=>{const r=t.details,s=r[r.length-1],l=s.column+s.colspan,a=Nl(r),c=A(a,((e,t)=>pl(e,l,t.column,o,n.getOrInit)),e);return Gl(c,r[0].row,l)}),sa(!1),ta,f,_l),fa=Js(((e,t,o,n)=>{const r=Nl(t.details),s=((e,t)=>j(e,(e=>{const o=e.cells,n=A(t,((e,t)=>t>=0&&t0?[Ye(e.element,n,e.section,e.isNew)]:[]})))(e,E(r,(e=>e.column))),l=s.length>0?s[0].cells.length-1:0;return Gl(s,r[0].row,Math.min(r[0].column,l))}),((e,t)=>Zs(e,t).map((t=>({details:t,pixelDelta:-ra(e,t)})))),ta,$l,_l),ga=Js(((e,t,o,n)=>{const r=Kl(t),s=((e,t,o)=>{const{rows:n,cols:r}=jo(e);return[...r,...n.slice(0,t),...n.slice(o+1)]})(e,r[0].row,r[r.length-1].row),l=s.length>0?s.length-1:0;return Gl(s,Math.min(t[0].row,l),t[0].column)}),Xs,f,$l,_l),ha=Js(((e,t,o,n)=>{const r=Nl(t),s=E(r,(e=>e.column)),l=Cl(e,s,!0,o,n.replaceOrInit);return Gl(l,t[0].row,t[0].column)}),Zs,f,f,aa),pa=Js(((e,t,o,n)=>{const r=Nl(t),s=E(r,(e=>e.column)),l=Cl(e,s,!1,o,n.replaceOrInit);return Gl(l,t[0].row,t[0].column)}),Zs,f,f,ca),wa=Js(Jl,Zs,f,f,aa),ba=Js(Ql,Zs,f,f,ca),va=Js(Xl,Zs,f,f,ca),ya=Js(((e,t,o,n)=>{const r=Sl(e,t,o,n.replaceOrInit);return Gl(r,t[0].row,t[0].column)}),Zs,f,f,aa),xa=Js(((e,t,o,n)=>{const r=Sl(e,t,o,n.replaceOrInit);return Gl(r,t[0].row,t[0].column)}),Zs,f,f,ca),Ca=Js(((e,t,o,n)=>{const r=t.cells;ql(r);const s=((e,t,o,n)=>{const r=jo(e).rows;if(0===r.length)return e;for(let e=t.startRow;e<=t.finishRow;e++)for(let o=t.startCol;o<=t.finishCol;o++){const t=r[e],s=Lo(t,o).isLocked;Ao(t,o,Ke(n(),!1,s))}return e})(e,t.bounds,0,n.merge(r));return Ul(s,C.from(r[0]))}),((e,t)=>((e,t)=>t.mergable)(0,t).filter((t=>el(e,t.cells)))),ea,f,jl),Sa=Js(((e,t,o,n)=>{const r=A(t,((e,t)=>tl(e,t,o,n.unmerge(t))),e);return Ul(r,C.from(t[0]))}),((e,t)=>((e,t)=>t.unmergable)(0,t).filter((t=>el(e,t)))),ea,f,jl),Ta=Js(((e,t,o,n)=>{const r=((e,t)=>{const o=Uo(e);return Us(o,t,!0)})(t.clipboard,t.generators);var s,l;return((e,t,o,n,r)=>{const s=Ho(t),l=((e,t,o)=>{const n=Mo(t[0]),r=jo(t).cols.length+e.row,s=k(n-e.column,(t=>t+e.column));return{row:r,column:L(s,(e=>I(o,(t=>t!==e)))).getOr(n-1)}})(e,t,s),a=jo(o).rows,c=ul(l,a,s),i=((e,t,o)=>{if(e.row>=t.length||e.column>Mo(t[0]))return rl.error("invalid start address out of table bounds, row: "+e.row+", column: "+e.column);const n=t.slice(e.row),r=n[0].cells.slice(e.column),s=Mo(o[0]),l=o.length;return rl.value({rowDelta:n.length-l,colDelta:r.length-s})})(l,t,a);return i.map((e=>{const o={...e,colDelta:e.colDelta-c.length},s=ml(t,o,n),i=Ho(s),m=ul(l,a,i);return((e,t,o,n,r,s)=>{const l=e.row,a=e.column,c=l+o.length,i=a+Mo(o[0])+s.length,m=P(s,x);for(let e=l;eUl(e,C.some(t.element))),(e=>Gl(e,t.row,t.column)))}),((e,t)=>jt(t.element).bind((o=>Ks(e,o).map((e=>({...e,generators:t.generators,clipboard:t.clipboard})))))),ea,f,_l),Ra=Js(((e,t,o,n)=>{const r=jo(e).rows,s=t.cells[0].column,l=r[t.cells[0].row],a=Zl(t.clipboard,t.generators,l),c=fl(s,e,a,t.generators,o);return Gl(c,t.cells[0].row,t.cells[0].column)}),la(!0),f,f,_l),Da=Js(((e,t,o,n)=>{const r=jo(e).rows,s=t.cells[t.cells.length-1].column+t.cells[t.cells.length-1].colspan,l=r[t.cells[0].row],a=Zl(t.clipboard,t.generators,l),c=fl(s,e,a,t.generators,o);return Gl(c,t.cells[0].row,t.cells[0].column)}),la(!1),f,f,_l),Oa=Js(((e,t,o,n)=>{const r=jo(e).rows,s=t.cells[0].row,l=r[s],a=Zl(t.clipboard,t.generators,l),c=gl(s,e,a,t.generators,o);return Gl(c,t.cells[0].row,t.cells[0].column)}),Qs,f,f,_l),ka=Js(((e,t,o,n)=>{const r=jo(e).rows,s=t.cells[t.cells.length-1].row+t.cells[t.cells.length-1].rowspan,l=r[t.cells[0].row],a=Zl(t.clipboard,t.generators,l),c=gl(s,e,a,t.generators,o);return Gl(c,t.cells[0].row,t.cells[0].column)}),Qs,f,f,_l),Ea=(e,t)=>{const o=Uo(e);return Xs(o,t).bind((e=>{const t=e[e.length-1],n=e[0].column,r=t.column+t.colspan,s=M(E(o.all,(e=>z(e.cells,(e=>e.column>=n&&e.column{const o=Uo(e);return Xs(o,t).bind(ks).getOr("")},Ba=(e,t)=>{const o=Uo(e);return Xs(o,t).bind((e=>{const t=e[e.length-1],n=e[0].row,r=t.row+t.rowspan;return(e=>{const t=E(e,(e=>Os(e).type)),o=D(t,"header"),n=D(t,"footer");if(o||n){const e=D(t,"body");return!o||e||n?o||e||!n?C.none():C.some("footer"):C.some("header")}return C.some("body")})(o.all.slice(n,r))})).getOr("")},za=(e,t)=>e.dispatch("NewRow",{node:t}),Aa=(e,t)=>e.dispatch("NewCell",{node:t}),Wa=(e,t,o)=>{e.dispatch("TableModified",{...o,table:t})},La={structure:!1,style:!0},_a={structure:!0,style:!1},Ma={structure:!0,style:!0},ja=e=>t=>t.options.get(e),Ia="100%",Pa=e=>{var t;const o=e.dom,n=null!==(t=o.getParent(e.selection.getStart(),o.isBlock))&&void 0!==t?t:e.getBody();return No(pe.fromDom(n))+"px"},Fa=e=>C.from(e.options.get("table_clone_elements")),Ha=ja("table_header_type"),qa=ja("table_column_resizing"),Va=e=>"preservetable"===qa(e),$a=e=>"resizetable"===qa(e),Ua=ja("table_sizing_mode"),Ga=e=>"relative"===Ua(e),Ka=e=>"fixed"===Ua(e),Ya=e=>"responsive"===Ua(e),Ja=ja("table_resize_bars"),Qa=ja("table_style_by_css"),Xa=e=>{const t=e.options,o=t.get("table_default_attributes");return t.isSet("table_default_attributes")?o:((e,t)=>Ya(e)||Qa(e)?t:Ka(e)?{...t,width:Pa(e)}:{...t,width:Ia})(e,o)},Za=ja("table_use_colgroups"),ec=(e,t)=>Ga(e)?sr(t):Ka(e)?rr(t):nr(t),tc=(e,t,o)=>{const n=e=>"table"===Z(Dr(e)),r=Fa(e),s=$a(e)?f:hs,l=t=>{switch(Ha(e)){case"section":return Ws();case"sectionCells":return Ls();case"cells":return _s();default:return((e,t)=>{var o;switch((o=Uo(e),V(o.all,(e=>{const t=Os(e);return"header"===t.type?C.from(t.subType):C.none()}))).getOr(t)){case"section":return Bs();case"sectionCells":return zs();case"cells":return As()}})(t,"section")}},a=(n,s,a,c)=>(i,m,d=!1)=>{kr(i);const u=pe.fromDom(e.getDoc()),f=Tr(a,u,r),g={sizing:ec(e,i),resize:$a(e)?xs():Cs(),section:l(i)};return s(i)?n(i,m,f,g).bind((n=>{t.refresh(i.dom),N(n.newRows,(t=>{za(e,t.dom)})),N(n.newCells,(t=>{Aa(e,t.dom)}));const r=((t,n)=>n.cursor.fold((()=>{const n=It(t);return H(n).filter(et).map((n=>{o.clearSelectedCells(t.dom);const r=e.dom.createRng();return r.selectNode(n.dom),e.selection.setRng(r),ie(n,"data-mce-selected","1"),r}))}),(n=>{const r=fs(gs,n),s=e.dom.createRng();return s.setStart(r.element.dom,r.offset),s.setEnd(r.element.dom,r.offset),e.selection.setRng(s),o.clearSelectedCells(t.dom),C.some(s)})))(i,n);return et(i)&&(kr(i),d||Wa(e,i.dom,c)),r.map((e=>({rng:e,effect:c})))})):C.none()},c=a(ga,(t=>!n(e)||Ss(t).rows>1),f,_a),i=a(fa,(t=>!n(e)||Ss(t).columns>1),f,_a);return{deleteRow:c,deleteColumn:i,insertRowsBefore:a(ia,x,f,_a),insertRowsAfter:a(ma,x,f,_a),insertColumnsBefore:a(da,x,s,_a),insertColumnsAfter:a(ua,x,s,_a),mergeCells:a(Ca,x,f,_a),unmergeCells:a(Sa,x,f,_a),pasteColsBefore:a(Ra,x,f,_a),pasteColsAfter:a(Da,x,f,_a),pasteRowsBefore:a(Oa,x,f,_a),pasteRowsAfter:a(ka,x,f,_a),pasteCells:a(Ta,x,f,Ma),makeCellsHeader:a(ya,x,f,_a),unmakeCellsHeader:a(xa,x,f,_a),makeColumnsHeader:a(ha,x,f,_a),unmakeColumnsHeader:a(pa,x,f,_a),makeRowsHeader:a(wa,x,f,_a),makeRowsBody:a(ba,x,f,_a),makeRowsFooter:a(va,x,f,_a),getTableRowType:Ba,getTableCellType:Na,getTableColType:Ea}},oc=(e,t,o)=>{const n=Et(e,t,1);1===o||n<=1?fe(e,t):ie(e,t,Math.min(o,n))},nc=(e,t)=>o=>{const n=o.column+o.colspan-1,r=o.column;return n>=e&&r{const n=o.substring(0,o.length-e.length),r=parseFloat(n);return n===r.toString()?t(r):rc.invalid(o)},lc={...rc,from:e=>bt(e,"%")?sc("%",rc.percent,e):bt(e,"px")?sc("px",rc.pixels,e):rc.invalid(e)},ac=(e,t,o)=>{const n=lc.from(o),r=I(e,(e=>"0px"===e))?((e,t)=>{const o=e.fold((()=>g("")),(e=>g(e/t+"px")),(()=>g(100/t+"%")));return k(t,o)})(n,e.length):((e,t,o)=>e.fold((()=>t),(e=>((e,t,o)=>{const n=o/t;return E(e,(e=>lc.from(e).fold((()=>e),(e=>e*n+"px"),(e=>e/100*o+"px"))))})(t,o,e)),(e=>((e,t)=>E(e,(e=>lc.from(e).fold((()=>e),(e=>e/t*100+"%"),(e=>e+"%")))))(t,o))))(n,e,t);return mc(r)},cc=(e,t)=>0===e.length?t:A(e,((e,t)=>lc.from(t).fold(g(0),h,h)+e),0),ic=(e,t)=>lc.from(e).fold(g(e),(e=>e+t+"px"),(e=>e+t+"%")),mc=e=>{if(0===e.length)return e;const t=A(e,((e,t)=>{const o=lc.from(t).fold((()=>({value:t,remainder:0})),(e=>((e,t)=>{const o=Math.floor(e);return{value:o+"px",remainder:e-o}})(e)),(e=>({value:e+"%",remainder:0})));return{output:[o.value].concat(e.output),remainder:e.remainder+o.remainder}}),{output:[],remainder:0}),o=t.output;return o.slice(0,o.length-1).concat([ic(o[o.length-1],Math.round(t.remainder))])},dc=lc.from,uc=e=>dc(e).fold(g("px"),g("px"),g("%")),fc=(e,t,o)=>{const n=Uo(e),r=n.all,s=Qo(n),l=Xo(n);t.each((t=>{const o=uc(t),r=ko(e),a=((e,t)=>Jn(e,t,Gn,Qn))(n,e),c=ac(a,r,t);Zo(n)?((e,t,o)=>{N(t,((t,n)=>{const r=cc([e[n]],Wt());St(t.element,"width",r+o)}))})(c,l,o):((e,t,o)=>{N(t,(t=>{const n=e.slice(t.column,t.colspan+t.column),r=cc(n,Wt());St(t.element,"width",r+o)}))})(c,s,o),St(e,"width",t)})),o.each((t=>{const o=uc(t),l=an(e),a=((e,t,o)=>Zn(e,t,o,Kn,Qn))(n,e,Rn);((e,t,o,n)=>{N(o,(t=>{const o=e.slice(t.row,t.rowspan+t.row),r=cc(o,Lt());St(t.element,"height",r+n)})),N(t,((t,o)=>{St(t.element,"height",e[o])}))})(ac(a,l,t),r,s,o),St(e,"height",t)}))},gc=e=>In(e).exists((e=>Nn.test(e))),hc=e=>In(e).exists((e=>Bn.test(e))),pc=e=>In(e).isNone(),wc=e=>{fe(e,"width")},bc=e=>{const t=Vn(e);fc(e,C.some(t),C.none()),wc(e)},vc=e=>{const t=(e=>ko(e)+"px")(e);fc(e,C.some(t),C.none()),wc(e)},yc=e=>{kt(e,"width");const t=Pt(e),o=t.length>0?t:It(e);N(o,(e=>{kt(e,"width"),wc(e)})),wc(e)},xc={styles:{"border-collapse":"collapse",width:"100%"},attributes:{border:"1"},colGroups:!1},Cc=(e,t,o,n)=>k(e,(e=>((e,t,o,n)=>{const r=pe.fromTag("tr");for(let s=0;s{e.selection.select(t.dom,!0),e.selection.collapse(!0)},Tc=(e,t,o,n,s)=>{const l=(e=>{const t=e.options,o=t.get("table_default_styles");return t.isSet("table_default_styles")?o:((e,t)=>Ya(e)||!Qa(e)?t:Ka(e)?{...t,width:Pa(e)}:{...t,width:Ia})(e,o)})(e),a={styles:l,attributes:Xa(e),colGroups:Za(e)};return e.undoManager.ignore((()=>{const r=((e,t,o,n,r,s=xc)=>{const l=pe.fromTag("table"),a="cells"!==r;Tt(l,s.styles),me(l,s.attributes),s.colGroups&&We(l,(e=>{const t=pe.fromTag("colgroup");return k(e,(()=>We(t,pe.fromTag("col")))),t})(t));const c=Math.min(e,o);if(a&&o>0){const e=pe.fromTag("thead");We(l,e);const s=Cc(o,t,"sectionCells"===r?c:0,n);Me(e,s)}const i=pe.fromTag("tbody");We(l,i);const m=Cc(a?e-c:e,t,a?0:o,n);return Me(i,m),l})(o,t,s,n,Ha(e),a);ie(r,"data-mce-id","__mce");const l=(e=>{const t=pe.fromTag("div"),o=pe.fromDom(e.dom.cloneNode(!0));return We(t,o),(e=>e.dom.innerHTML)(t)})(r);e.insertContent(l),e.addVisual()})),mt(Dr(e),'table[data-mce-id="__mce"]').map((t=>(Ka(e)?vc(t):Ya(e)?yc(t):(Ga(e)||(e=>r(e)&&-1!==e.indexOf("%"))(l.width))&&bc(t),kr(t),fe(t,"data-mce-id"),((e,t)=>{N(st(t,"tr"),(t=>{za(e,t.dom),N(st(t,"th,td"),(t=>{Aa(e,t.dom)}))}))})(e,t),((e,t)=>{mt(t,"td,th").each(w(Sc,e))})(e,t),t.dom))).getOrNull()};var Rc=tinymce.util.Tools.resolve("tinymce.FakeClipboard");const Dc="x-tinymce/dom-table-",Oc=Dc+"rows",kc=Dc+"columns",Ec=e=>{const t=Rc.FakeClipboardItem(e);Rc.write([t])},Nc=e=>{var t;const o=null!==(t=Rc.read())&&void 0!==t?t:[];return V(o,(t=>C.from(t.getType(e))))},Bc=e=>{Nc(e).isSome()&&Rc.clear()},zc=e=>{e.fold(Wc,(e=>Ec({[Oc]:e})))},Ac=()=>Nc(Oc),Wc=()=>Bc(Oc),Lc=e=>{e.fold(Mc,(e=>Ec({[kc]:e})))},_c=()=>Nc(kc),Mc=()=>Bc(kc),jc=e=>ss(Er(e),Or(e)),Ic=(e,t)=>{const o=Or(e),n=e=>Ft(e,o),l=t=>(e=>ls(Er(e),Or(e)))(e).bind((e=>n(e).map((o=>t(o,e))))),a=t=>{e.focus()},c=(t,o=!1)=>l(((n,r)=>{const s=ns(as(e),n,r);t(n,s,o).each(a)})),i=()=>l(((t,o)=>((e,t,o)=>{const n=Uo(e);return Xs(n,t).bind((e=>{const t=Us(n,o,!1),r=jo(t).rows.slice(e[0].row,e[e.length-1].row+e[e.length-1].rowspan),s=j(r,(e=>{const t=z(e.cells,(e=>!e.isLocked));return t.length>0?[{...e,cells:t}]:[]})),l=Gs(s);return gt(l.length>0,l)})).map((e=>E(e,(e=>{const t=He(e.element);return N(e.cells,(e=>{const o=qe(e.element);Fs(o,"colspan",e.colspan,1),Fs(o,"rowspan",e.rowspan,1),We(t,o)})),t}))))})(t,ns(as(e),t,o),Tr(f,pe.fromDom(e.getDoc()),C.none())))),m=()=>l(((t,o)=>((e,t)=>{const o=Uo(e);return Zs(o,t).map((e=>{const t=e[e.length-1],n=e[0].column,r=t.column+t.colspan,s=((e,t,o)=>{if(Zo(e)){const n=z(Xo(e),nc(t,o)),r=E(n,(e=>{const n=qe(e.element);return oc(n,"span",o-t),n})),s=pe.fromTag("colgroup");return Me(s,r),[s]}return[]})(o,n,r),l=((e,t,o)=>E(e.all,(e=>{const n=z(e.cells,nc(t,o)),r=E(n,(e=>{const n=qe(e.element);return oc(n,"colspan",o-t),n})),s=pe.fromTag("tr");return Me(s,r),s})))(o,n,r);return[...s,...l]}))})(t,ns(as(e),t,o)))),d=(t,o)=>o().each((o=>{const n=E(o,(e=>qe(e)));l(((o,r)=>{const s=Rr(pe.fromDom(e.getDoc())),l=((e,t,o,n)=>({selection:Zr(e),clipboard:o,generators:n}))(as(e),0,n,s);t(o,l).each(a)}))})),g=e=>(t,o)=>((e,t)=>X(e,t)?C.from(e.type):C.none())(o,"type").each((t=>{c(e(t),o.no_events)}));G({mceTableSplitCells:()=>c(t.unmergeCells),mceTableMergeCells:()=>c(t.mergeCells),mceTableInsertRowBefore:()=>c(t.insertRowsBefore),mceTableInsertRowAfter:()=>c(t.insertRowsAfter),mceTableInsertColBefore:()=>c(t.insertColumnsBefore),mceTableInsertColAfter:()=>c(t.insertColumnsAfter),mceTableDeleteCol:()=>c(t.deleteColumn),mceTableDeleteRow:()=>c(t.deleteRow),mceTableCutCol:()=>m().each((e=>{Lc(e),c(t.deleteColumn)})),mceTableCutRow:()=>i().each((e=>{zc(e),c(t.deleteRow)})),mceTableCopyCol:()=>m().each((e=>Lc(e))),mceTableCopyRow:()=>i().each((e=>zc(e))),mceTablePasteColBefore:()=>d(t.pasteColsBefore,_c),mceTablePasteColAfter:()=>d(t.pasteColsAfter,_c),mceTablePasteRowBefore:()=>d(t.pasteRowsBefore,Ac),mceTablePasteRowAfter:()=>d(t.pasteRowsAfter,Ac),mceTableDelete:()=>jc(e).each((t=>{Ft(t,o).filter(b(o)).each((t=>{const o=pe.fromText("");if(ze(t,o),Ie(t),e.dom.isEmpty(e.getBody()))e.setContent(""),e.selection.setCursorLocation();else{const t=e.dom.createRng();t.setStart(o.dom,0),t.setEnd(o.dom,0),e.selection.setRng(t),e.nodeChanged()}}))})),mceTableCellToggleClass:(t,o)=>{l((t=>{const n=as(e),r=I(n,(t=>e.formatter.match("tablecellclass",{value:o},t.dom))),s=r?e.formatter.remove:e.formatter.apply;N(n,(e=>s("tablecellclass",{value:o},e.dom))),Wa(e,t.dom,La)}))},mceTableToggleClass:(t,o)=>{l((t=>{e.formatter.toggle("tableclass",{value:o},t.dom),Wa(e,t.dom,La)}))},mceTableToggleCaption:()=>{jc(e).each((t=>{Ft(t,o).each((o=>{it(o,"caption").fold((()=>{const t=pe.fromTag("caption");We(t,pe.fromText("Caption")),((e,t,o)=>{Ne(e,0).fold((()=>{We(e,t)}),(e=>{Be(e,t)}))})(o,t),e.selection.setCursorLocation(t.dom,0)}),(n=>{ae("caption")(t)&&ve("td",o).each((t=>e.selection.setCursorLocation(t.dom,0))),Ie(n)})),Wa(e,o.dom,_a)}))}))},mceTableSizingMode:(t,n)=>(t=>jc(e).each((n=>{Ya(e)||Ka(e)||Ga(e)||Ft(n,o).each((o=>{"relative"!==t||gc(o)?"fixed"!==t||hc(o)?"responsive"!==t||pc(o)||yc(o):vc(o):bc(o),kr(o),Wa(e,o.dom,_a)}))})))(n),mceTableCellType:g((e=>"th"===e?t.makeCellsHeader:t.unmakeCellsHeader)),mceTableColType:g((e=>"th"===e?t.makeColumnsHeader:t.unmakeColumnsHeader)),mceTableRowType:g((e=>{switch(e){case"header":return t.makeRowsHeader;case"footer":return t.makeRowsFooter;default:return t.makeRowsBody}}))},((t,o)=>e.addCommand(o,t))),e.addCommand("mceInsertTable",((t,o)=>{((e,t,o,n={})=>{const r=e=>u(e)&&e>0;if(r(t)&&r(o)){const r=n.headerRows||0,s=n.headerColumns||0;return Tc(e,o,t,s,r)}console.error("Invalid values for mceInsertTable - rows and columns values are required to insert a table.")})(e,o.rows,o.columns,o.options)})),e.addCommand("mceTableApplyCellStyle",((t,o)=>{const l=e=>"tablecell"+e.toLowerCase().replace("-","");if(!s(o))return;const a=as(e);if(0===a.length)return;const c=((e,t)=>{const o={};return((e,t,o,n)=>{G(e,((e,r)=>{(t(e,r)?o:n)(e,r)}))})(e,t,(e=>(t,o)=>{e[o]=t})(o),f),o})(o,((t,o)=>e.formatter.has(l(o))&&r(t)));(e=>{for(const t in e)if(U.call(e,t))return!1;return!0})(c)||(G(c,((t,o)=>{const n=l(o);N(a,(o=>{""===t?e.formatter.remove(n,{value:null},o.dom,!0):e.formatter.apply(n,{value:t},o.dom)}))})),n(a[0]).each((t=>Wa(e,t.dom,La))))}))},Pc=Tl([{before:["element"]},{on:["element","offset"]},{after:["element"]}]),Fc={before:Pc.before,on:Pc.on,after:Pc.after,cata:(e,t,o,n)=>e.fold(t,o,n),getStart:e=>e.fold(h,h,h)},Hc=(e,t)=>({selection:e,kill:t}),qc=(e,t)=>{const o=e.document.createRange();return o.selectNode(t.dom),o},Vc=(e,t)=>{const o=e.document.createRange();return $c(o,t),o},$c=(e,t)=>e.selectNodeContents(t.dom),Uc=(e,t,o)=>{const n=e.document.createRange();var r;return r=n,t.fold((e=>{r.setStartBefore(e.dom)}),((e,t)=>{r.setStart(e.dom,t)}),(e=>{r.setStartAfter(e.dom)})),((e,t)=>{t.fold((t=>{e.setEndBefore(t.dom)}),((t,o)=>{e.setEnd(t.dom,o)}),(t=>{e.setEndAfter(t.dom)}))})(n,o),n},Gc=(e,t,o,n,r)=>{const s=e.document.createRange();return s.setStart(t.dom,o),s.setEnd(n.dom,r),s},Kc=e=>({left:e.left,top:e.top,right:e.right,bottom:e.bottom,width:e.width,height:e.height}),Yc=Tl([{ltr:["start","soffset","finish","foffset"]},{rtl:["start","soffset","finish","foffset"]}]),Jc=(e,t,o)=>t(pe.fromDom(o.startContainer),o.startOffset,pe.fromDom(o.endContainer),o.endOffset),Qc=(e,t)=>{const o=((e,t)=>t.match({domRange:e=>({ltr:g(e),rtl:C.none}),relative:(t,o)=>({ltr:Gt((()=>Uc(e,t,o))),rtl:Gt((()=>C.some(Uc(e,o,t))))}),exact:(t,o,n,r)=>({ltr:Gt((()=>Gc(e,t,o,n,r))),rtl:Gt((()=>C.some(Gc(e,n,r,t,o))))})}))(e,t);return((e,t)=>{const o=t.ltr();return o.collapsed?t.rtl().filter((e=>!1===e.collapsed)).map((e=>Yc.rtl(pe.fromDom(e.endContainer),e.endOffset,pe.fromDom(e.startContainer),e.startOffset))).getOrThunk((()=>Jc(0,Yc.ltr,o))):Jc(0,Yc.ltr,o)})(0,o)},Xc=(e,t)=>Qc(e,t).match({ltr:(t,o,n,r)=>{const s=e.document.createRange();return s.setStart(t.dom,o),s.setEnd(n.dom,r),s},rtl:(t,o,n,r)=>{const s=e.document.createRange();return s.setStart(n.dom,r),s.setEnd(t.dom,o),s}});Yc.ltr,Yc.rtl;const Zc=(e,t,o,n)=>({start:e,soffset:t,finish:o,foffset:n}),ei=(e,t,o,n)=>({start:Fc.on(e,t),finish:Fc.on(o,n)}),ti=(e,t)=>{const o=Xc(e,t);return Zc(pe.fromDom(o.startContainer),o.startOffset,pe.fromDom(o.endContainer),o.endOffset)},oi=ei,ni=(e,t,o,n,r)=>ye(o,n)?C.none():Gr(o,n,t).bind((t=>{const n=t.boxes.getOr([]);return n.length>1?(r(e,n,t.start,t.finish),C.some(Hc(C.some(oi(o,0,o,dr(o))),!0))):C.none()})),ri=(e,t)=>({item:e,mode:t}),si=(e,t,o,n=li)=>e.property().parent(t).map((e=>ri(e,n))),li=(e,t,o,n=ai)=>o.sibling(e,t).map((e=>ri(e,n))),ai=(e,t,o,n=ai)=>{const r=e.property().children(t);return o.first(r).map((e=>ri(e,n)))},ci=[{current:si,next:li,fallback:C.none()},{current:li,next:ai,fallback:C.some(si)},{current:ai,next:ai,fallback:C.some(li)}],ii=(e,t,o,n,r=ci)=>L(r,(e=>e.current===o)).bind((o=>o.current(e,t,n,o.next).orThunk((()=>o.fallback.bind((o=>ii(e,t,o,n))))))),mi=(e,t,o,n,r,s)=>ii(e,t,n,r).bind((t=>s(t.item)?C.none():o(t.item)?C.some(t.item):mi(e,t.item,o,t.mode,r,s))),di=e=>t=>0===e.property().children(t).length,ui=(e,t,o,n)=>mi(e,t,o,li,{sibling:(e,t)=>e.query().prevSibling(t),first:e=>e.length>0?C.some(e[e.length-1]):C.none()},n),fi=(e,t,o,n)=>mi(e,t,o,li,{sibling:(e,t)=>e.query().nextSibling(t),first:e=>e.length>0?C.some(e[0]):C.none()},n),gi=Fr(),hi=(e,t)=>((e,t,o)=>ui(e,t,di(e),o))(gi,e,t),pi=(e,t)=>((e,t,o)=>fi(e,t,di(e),o))(gi,e,t),wi=Tl([{none:["message"]},{success:[]},{failedUp:["cell"]},{failedDown:["cell"]}]),bi=e=>dt(e,"tr"),vi={...wi,verify:(e,t,o,n,r,s,l)=>dt(n,"td,th",l).bind((o=>dt(t,"td,th",l).map((t=>ye(o,t)?ye(n,o)&&dr(o)===r?s(t):wi.none("in same cell"):$r(bi,[o,t]).fold((()=>((e,t,o)=>{const n=e.getRect(t),r=e.getRect(o);return r.right>n.left&&r.lefts(t))))))).getOr(wi.none("default")),cata:(e,t,o,n,r)=>e.fold(t,o,n,r)},yi=ae("br"),xi=(e,t,o)=>t(e,o).bind((e=>re(e)&&0===cr(e).trim().length?xi(e,t,o):C.some(e))),Ci=(e,t,o,n)=>((e,t)=>Ne(e,t).filter(yi).orThunk((()=>Ne(e,t-1).filter(yi))))(t,o).bind((t=>n.traverse(t).fold((()=>xi(t,n.gather,e).map(n.relative)),(e=>(e=>Re(e).bind((t=>{const o=Ee(t);return((e,t)=>_(e,w(ye,t)))(o,e).map((n=>((e,t,o,n)=>({parent:e,children:t,element:o,index:n}))(t,o,e,n)))})))(e).map((e=>Fc.on(e.parent,e.index))))))),Si=(e,t)=>({left:e.left,top:e.top+t,right:e.right,bottom:e.bottom+t}),Ti=(e,t)=>({left:e.left,top:e.top-t,right:e.right,bottom:e.bottom-t}),Ri=(e,t,o)=>({left:e.left+t,top:e.top+o,right:e.right+t,bottom:e.bottom+o}),Di=e=>({left:e.left,top:e.top,right:e.right,bottom:e.bottom}),Oi=(e,t)=>C.some(e.getRect(t)),ki=(e,t,o)=>ne(t)?Oi(e,t).map(Di):re(t)?((e,t,o)=>o>=0&&o0?e.getRangedRect(t,o-1,t,o):C.none())(e,t,o).map(Di):C.none(),Ei=(e,t)=>ne(t)?Oi(e,t).map(Di):re(t)?e.getRangedRect(t,0,t,dr(t)).map(Di):C.none(),Ni=Tl([{none:[]},{retry:["caret"]}]),Bi=(e,t,o)=>{return(n=t,r=Fl,lt(((e,t)=>t(e)),at,n,r,undefined)).fold(y,(t=>Ei(e,t).exists((e=>((e,t)=>e.leftt.right)(o,e)))));var n,r},zi={point:e=>e.bottom,adjuster:(e,t,o,n,r)=>{const s=Si(r,5);return Math.abs(o.bottom-n.bottom)<1||o.top>r.bottom?Ni.retry(s):o.top===r.bottom?Ni.retry(Si(r,1)):Bi(e,t,r)?Ni.retry(Ri(s,5,0)):Ni.none()},move:Si,gather:pi},Ai=(e,t,o,n,r)=>0===r?C.some(n):((e,t,o)=>e.elementFromPoint(t,o).filter((e=>"table"===Z(e))).isSome())(e,n.left,t.point(n))?((e,t,o,n,r)=>Ai(e,t,o,t.move(n,5),r))(e,t,o,n,r-1):e.situsFromPoint(n.left,t.point(n)).bind((s=>s.start.fold(C.none,(s=>Ei(e,s).bind((l=>t.adjuster(e,s,l,o,n).fold(C.none,(n=>Ai(e,t,o,n,r-1))))).orThunk((()=>C.some(n)))),C.none))),Wi=(e,t,o)=>{const n=e.move(o,5),r=Ai(t,e,o,n,100).getOr(n);return((e,t,o)=>e.point(t)>o.getInnerHeight()?C.some(e.point(t)-o.getInnerHeight()):e.point(t)<0?C.some(-e.point(t)):C.none())(e,r,t).fold((()=>t.situsFromPoint(r.left,e.point(r))),(o=>(t.scrollBy(0,o),t.situsFromPoint(r.left,e.point(r)-o))))},Li={tryUp:w(Wi,{point:e=>e.top,adjuster:(e,t,o,n,r)=>{const s=Ti(r,5);return Math.abs(o.top-n.top)<1||o.bottome.getSelection().bind((n=>((e,t,o,n)=>{const r=yi(t)?((e,t,o)=>o.traverse(t).orThunk((()=>xi(t,o.gather,e))).map(o.relative))(e,t,n):Ci(e,t,o,n);return r.map((e=>({start:e,finish:e})))})(t,n.finish,n.foffset,o).fold((()=>C.some(is(n.finish,n.foffset))),(r=>{const s=e.fromSitus(r);return l=vi.verify(e,n.finish,n.foffset,s.finish,s.foffset,o.failure,t),vi.cata(l,(e=>C.none()),(()=>C.none()),(e=>C.some(is(e,0))),(e=>C.some(is(e,dr(e)))));var l})))),Mi=(e,t,o,n,r,s)=>0===s?C.none():Pi(e,t,o,n,r).bind((l=>{const a=e.fromSitus(l),c=vi.verify(e,o,n,a.finish,a.foffset,r.failure,t);return vi.cata(c,(()=>C.none()),(()=>C.some(l)),(l=>ye(o,l)&&0===n?ji(e,o,n,Ti,r):Mi(e,t,l,0,r,s-1)),(l=>ye(o,l)&&n===dr(l)?ji(e,o,n,Si,r):Mi(e,t,l,dr(l),r,s-1)))})),ji=(e,t,o,n,r)=>ki(e,t,o).bind((t=>Ii(e,r,n(t,Li.getJumpSize())))),Ii=(e,t,o)=>{const n=To().browser;return n.isChromium()||n.isSafari()||n.isFirefox()?t.retry(e,o):C.none()},Pi=(e,t,o,n,r)=>ki(e,o,n).bind((t=>Ii(e,r,t))),Fi=(e,t,o,n,r)=>dt(n,"td,th",t).bind((n=>dt(n,"table",t).bind((s=>((e,t)=>at(e,(e=>Re(e).exists((e=>ye(e,t)))),void 0).isSome())(r,s)?((e,t,o)=>_i(e,t,o).bind((n=>Mi(e,t,n.element,n.offset,o,20).map(e.fromSitus))))(e,t,o).bind((e=>dt(e.finish,"td,th",t).map((t=>({start:n,finish:t,range:e}))))):C.none())))),Hi=(e,t,o,n,r,s)=>s(n,t).orThunk((()=>Fi(e,t,o,n,r).map((e=>{const t=e.range;return Hc(C.some(oi(t.start,t.soffset,t.finish,t.foffset)),!0)})))),qi=(e,t)=>dt(e,"tr",t).bind((e=>dt(e,"table",t).bind((o=>{const n=st(o,"tr");return ye(e,n[0])?((e,t,o)=>ui(gi,e,(e=>hr(e).isSome()),o))(o,0,t).map((e=>{const t=dr(e);return Hc(C.some(oi(e,t,e,t)),!0)})):C.none()})))),Vi=(e,t)=>dt(e,"tr",t).bind((e=>dt(e,"table",t).bind((o=>{const n=st(o,"tr");return ye(e,n[n.length-1])?((e,t,o)=>fi(gi,e,(e=>gr(e).isSome()),o))(o,0,t).map((e=>Hc(C.some(oi(e,0,e,0)),!0))):C.none()})))),$i=(e,t,o,n,r,s,l)=>Fi(e,o,n,r,s).bind((e=>ni(t,o,e.start,e.finish,l))),Ui=e=>{let t=e;return{get:()=>t,set:e=>{t=e}}},Gi=()=>{const e=(e=>{const t=Ui(C.none()),o=()=>t.get().each(e);return{clear:()=>{o(),t.set(C.none())},isSet:()=>t.get().isSome(),get:()=>t.get(),set:e=>{o(),t.set(C.some(e))}}})(f);return{...e,on:t=>e.get().each(t)}},Ki=(e,t)=>dt(e,"td,th",t),Yi={traverse:ke,gather:pi,relative:Fc.before,retry:Li.tryDown,failure:vi.failedDown},Ji={traverse:Oe,gather:hi,relative:Fc.before,retry:Li.tryUp,failure:vi.failedUp},Qi=e=>t=>t===e,Xi=Qi(38),Zi=Qi(40),em=e=>e>=37&&e<=40,tm={isBackward:Qi(37),isForward:Qi(39)},om={isBackward:Qi(39),isForward:Qi(37)},nm=Tl([{domRange:["rng"]},{relative:["startSitu","finishSitu"]},{exact:["start","soffset","finish","foffset"]}]),rm={domRange:nm.domRange,relative:nm.relative,exact:nm.exact,exactFromRange:e=>nm.exact(e.start,e.soffset,e.finish,e.foffset),getWin:e=>{const t=(e=>e.match({domRange:e=>pe.fromDom(e.startContainer),relative:(e,t)=>Fc.getStart(e),exact:(e,t,o,n)=>e}))(e);return pe.fromDom(Te(t).dom.defaultView)},range:Zc},sm=document.caretPositionFromPoint?(e,t,o)=>{var n,r;return C.from(null===(r=(n=e.dom).caretPositionFromPoint)||void 0===r?void 0:r.call(n,t,o)).bind((t=>{if(null===t.offsetNode)return C.none();const o=e.dom.createRange();return o.setStart(t.offsetNode,t.offset),o.collapse(),C.some(o)}))}:document.caretRangeFromPoint?(e,t,o)=>{var n,r;return C.from(null===(r=(n=e.dom).caretRangeFromPoint)||void 0===r?void 0:r.call(n,t,o))}:C.none,lm=(e,t)=>{const o=Z(e);return"input"===o?Fc.after(e):D(["br","img"],o)?0===t?Fc.before(e):Fc.after(e):Fc.on(e,t)},am=e=>C.from(e.getSelection()),cm=(e,t)=>{am(e).each((e=>{e.removeAllRanges(),e.addRange(t)}))},im=(e,t,o,n,r)=>{const s=Gc(e,t,o,n,r);cm(e,s)},mm=(e,t)=>Qc(e,t).match({ltr:(t,o,n,r)=>{im(e,t,o,n,r)},rtl:(t,o,n,r)=>{am(e).each((s=>{if(s.setBaseAndExtent)s.setBaseAndExtent(t.dom,o,n.dom,r);else if(s.extend)try{((e,t,o,n,r,s)=>{t.collapse(o.dom,n),t.extend(r.dom,s)})(0,s,t,o,n,r)}catch(s){im(e,n,r,t,o)}else im(e,n,r,t,o)}))}}),dm=(e,t,o,n,r)=>{const s=((e,t,o,n)=>{const r=lm(e,t),s=lm(o,n);return rm.relative(r,s)})(t,o,n,r);mm(e,s)},um=(e,t,o)=>{const n=((e,t)=>{const o=e.fold(Fc.before,lm,Fc.after),n=t.fold(Fc.before,lm,Fc.after);return rm.relative(o,n)})(t,o);mm(e,n)},fm=e=>{if(e.rangeCount>0){const t=e.getRangeAt(0),o=e.getRangeAt(e.rangeCount-1);return C.some(Zc(pe.fromDom(t.startContainer),t.startOffset,pe.fromDom(o.endContainer),o.endOffset))}return C.none()},gm=e=>{if(null===e.anchorNode||null===e.focusNode)return fm(e);{const t=pe.fromDom(e.anchorNode),o=pe.fromDom(e.focusNode);return((e,t,o,n)=>{const r=((e,t,o,n)=>{const r=Se(e).dom.createRange();return r.setStart(e.dom,t),r.setEnd(o.dom,n),r})(e,t,o,n),s=ye(e,o)&&t===n;return r.collapsed&&!s})(t,e.anchorOffset,o,e.focusOffset)?C.some(Zc(t,e.anchorOffset,o,e.focusOffset)):fm(e)}},hm=(e,t,o=!0)=>{const n=(o?Vc:qc)(e,t);cm(e,n)},pm=e=>(e=>am(e).filter((e=>e.rangeCount>0)).bind(gm))(e).map((e=>rm.exact(e.start,e.soffset,e.finish,e.foffset))),wm=e=>({elementFromPoint:(t,o)=>pe.fromPoint(pe.fromDom(e.document),t,o),getRect:e=>e.dom.getBoundingClientRect(),getRangedRect:(t,o,n,r)=>{const s=rm.exact(t,o,n,r);return((e,t)=>(e=>{const t=e.getClientRects(),o=t.length>0?t[0]:e.getBoundingClientRect();return o.width>0||o.height>0?C.some(o).map(Kc):C.none()})(Xc(e,t)))(e,s)},getSelection:()=>pm(e).map((t=>ti(e,t))),fromSitus:t=>{const o=rm.relative(t.start,t.finish);return ti(e,o)},situsFromPoint:(t,o)=>((e,t,o)=>((e,t,o)=>{const n=pe.fromDom(e.document);return sm(n,t,o).map((e=>Zc(pe.fromDom(e.startContainer),e.startOffset,pe.fromDom(e.endContainer),e.endOffset)))})(e,t,o))(e,t,o).map((e=>ei(e.start,e.soffset,e.finish,e.foffset))),clearSelection:()=>{(e=>{am(e).each((e=>e.removeAllRanges()))})(e)},collapseSelection:(t=!1)=>{pm(e).each((o=>o.fold((e=>e.collapse(t)),((o,n)=>{const r=t?o:n;um(e,r,r)}),((o,n,r,s)=>{const l=t?o:r,a=t?n:s;dm(e,l,a,l,a)}))))},setSelection:t=>{dm(e,t.start,t.soffset,t.finish,t.foffset)},setRelativeSelection:(t,o)=>{um(e,t,o)},selectNode:t=>{hm(e,t,!1)},selectContents:t=>{hm(e,t)},getInnerHeight:()=>e.innerHeight,getScrollY:()=>(e=>{const t=void 0!==e?e.dom:document,o=t.body.scrollLeft||t.documentElement.scrollLeft,n=t.body.scrollTop||t.documentElement.scrollTop;return dn(o,n)})(pe.fromDom(e.document)).top,scrollBy:(t,o)=>{((e,t,o)=>{const n=(void 0!==o?o.dom:document).defaultView;n&&n.scrollBy(e,t)})(t,o,pe.fromDom(e.document))}}),bm=(e,t)=>({rows:e,cols:t}),vm=e=>void 0!==e.dom.classList,ym=(e,t)=>((e,t,o)=>{const n=((e,t)=>{const o=de(e,t);return void 0===o||""===o?[]:o.split(" ")})(e,t).concat([o]);return ie(e,t,n.join(" ")),!0})(e,"class",t),xm=(e,t)=>{vm(e)?e.dom.classList.add(t):ym(e,t)},Cm=(e,t)=>vm(e)&&e.dom.classList.contains(t),Sm=()=>({tag:"none"}),Tm=e=>({tag:"multiple",elements:e}),Rm=e=>({tag:"single",element:e}),Dm=e=>{const t=pe.fromDom((e=>{if(Qe()&&m(e.target)){const t=pe.fromDom(e.target);if(ne(t)&&m(t.dom.shadowRoot)&&e.composed&&e.composedPath){const t=e.composedPath();if(t)return H(t)}}return C.from(e.target)})(e).getOr(e.target)),o=()=>e.stopPropagation(),n=()=>e.preventDefault(),r=(s=n,l=o,(...e)=>s(l.apply(null,e)));var s,l;return((e,t,o,n,r,s,l)=>({target:e,x:t,y:o,stop:n,prevent:r,kill:s,raw:l}))(t,e.clientX,e.clientY,o,n,r,e)},Om=(e,t,o,n)=>{e.dom.removeEventListener(t,o,n)},km=x,Em=(e,t,o)=>((e,t,o,n)=>((e,t,o,n,r)=>{const s=((e,t)=>o=>{e(o)&&t(Dm(o))})(o,n);return e.dom.addEventListener(t,s,r),{unbind:w(Om,e,t,s,r)}})(e,t,o,n,!1))(e,t,km,o),Nm=Dm,Bm=e=>!Cm(pe.fromDom(e.target),"ephox-snooker-resizer-bar"),zm=(e,t)=>{const o=(r=os.selectedSelector,{get:()=>Qr(pe.fromDom(e.getBody()),r).fold((()=>ls(Er(e),Or(e)).fold(Sm,Rm)),Tm)}),n=((e,t,o)=>{const n=t=>{fe(t,e.selected),fe(t,e.firstSelected),fe(t,e.lastSelected)},r=t=>{ie(t,e.selected,"1")},s=e=>{l(e),o()},l=t=>{const o=st(t,`${e.selectedSelector},${e.firstSelectedSelector},${e.lastSelectedSelector}`);N(o,n)};return{clearBeforeUpdate:l,clear:s,selectRange:(o,n,l,a)=>{s(o),N(n,r),ie(l,e.firstSelected,"1"),ie(a,e.lastSelected,"1"),t(n,l,a)},selectedSelector:e.selectedSelector,firstSelectedSelector:e.firstSelectedSelector,lastSelectedSelector:e.lastSelectedSelector}})(os,((t,o,n)=>{Ft(o).each((r=>{const s=Fa(e),l=Tr(f,pe.fromDom(e.getDoc()),s),a=((e,t,o)=>{const n=Uo(e);return Xs(n,t).map((e=>{const t=Us(n,o,!1),{rows:r}=jo(t),s=((e,t)=>{const o=e.slice(0,t[t.length-1].row+1),n=Gs(o);return j(n,(e=>{const o=e.cells.slice(0,t[t.length-1].column+1);return E(o,(e=>e.element))}))})(r,e),l=((e,t)=>{const o=e.slice(t[0].row+t[0].rowspan-1,e.length),n=Gs(o);return j(n,(e=>{const o=e.cells.slice(t[0].column+t[0].colspan-1,e.cells.length);return E(o,(e=>e.element))}))})(r,e);return{upOrLeftCells:s,downOrRightCells:l}}))})(r,{selection:as(e)},l);((e,t,o,n,r)=>{e.dispatch("TableSelectionChange",{cells:t,start:o,finish:n,otherCells:r})})(e,t,o,n,a)}))}),(()=>(e=>{e.dispatch("TableSelectionClear")})(e)));var r;return e.on("init",(o=>{const r=e.getWin(),s=Dr(e),l=Or(e),a=((e,t,o,n)=>{const r=((e,t,o,n)=>{const r=Gi(),s=r.clear,l=s=>{r.on((r=>{n.clearBeforeUpdate(t),Ki(s.target,o).each((l=>{Gr(r,l,o).each((o=>{const r=o.boxes.getOr([]);if(1===r.length){const o=r[0],l="false"===Ps(o),a=ut(js(s.target),o,ye);l&&a&&(n.selectRange(t,r,o,o),e.selectContents(o))}else r.length>1&&(n.selectRange(t,r,o.start,o.finish),e.selectContents(l))}))}))}))};return{clearstate:s,mousedown:e=>{n.clear(t),Ki(e.target,o).each(r.set)},mouseover:e=>{l(e)},mouseup:e=>{l(e),s()}}})(wm(e),t,o,n);return{clearstate:r.clearstate,mousedown:r.mousedown,mouseover:r.mouseover,mouseup:r.mouseup}})(r,s,l,n),c=((e,t,o,n)=>{const r=wm(e),s=()=>(n.clear(t),C.none());return{keydown:(e,l,a,c,i,m)=>{const d=e.raw,u=d.which,f=!0===d.shiftKey,g=Kr(t,n.selectedSelector).fold((()=>(em(u)&&!f&&n.clearBeforeUpdate(t),Zi(u)&&f?w($i,r,t,o,Yi,c,l,n.selectRange):Xi(u)&&f?w($i,r,t,o,Ji,c,l,n.selectRange):Zi(u)?w(Hi,r,o,Yi,c,l,Vi):Xi(u)?w(Hi,r,o,Ji,c,l,qi):C.none)),(e=>{const o=o=>()=>{const s=V(o,(o=>((e,t,o,n,r)=>Jr(n,e,t,r.firstSelectedSelector,r.lastSelectedSelector).map((e=>(r.clearBeforeUpdate(o),r.selectRange(o,e.boxes,e.start,e.finish),e.boxes))))(o.rows,o.cols,t,e,n)));return s.fold((()=>Yr(t,n.firstSelectedSelector,n.lastSelectedSelector).map((e=>{const o=Zi(u)||m.isForward(u)?Fc.after:Fc.before;return r.setRelativeSelection(Fc.on(e.first,0),o(e.table)),n.clear(t),Hc(C.none(),!0)}))),(e=>C.some(Hc(C.none(),!0))))};return Zi(u)&&f?o([bm(1,0)]):Xi(u)&&f?o([bm(-1,0)]):m.isBackward(u)&&f?o([bm(0,-1),bm(-1,0)]):m.isForward(u)&&f?o([bm(0,1),bm(1,0)]):em(u)&&!f?s:C.none}));return g()},keyup:(e,r,s,l,a)=>Kr(t,n.selectedSelector).fold((()=>{const c=e.raw,i=c.which;return!0===c.shiftKey&&em(i)?((e,t,o,n,r,s,l)=>ye(o,r)&&n===s?C.none():dt(o,"td,th",t).bind((o=>dt(r,"td,th",t).bind((n=>ni(e,t,o,n,l))))))(t,o,r,s,l,a,n.selectRange):C.none()}),C.none)}})(r,s,l,n),i=((e,t,o,n)=>{const r=wm(e);return(e,s)=>{n.clearBeforeUpdate(t),Gr(e,s,o).each((e=>{const o=e.boxes.getOr([]);n.selectRange(t,o,e.start,e.finish),r.selectContents(s),r.collapseSelection()}))}})(r,s,l,n);e.on("TableSelectorChange",(e=>i(e.start,e.finish)));const m=(t,o)=>{(e=>!0===e.raw.shiftKey)(t)&&(o.kill&&t.kill(),o.selection.each((t=>{const o=rm.relative(t.start,t.finish),n=Xc(r,o);e.selection.setRng(n)})))},d=e=>0===e.button,u=(()=>{const e=Ui(pe.fromDom(s)),t=Ui(0);return{touchEnd:o=>{const n=pe.fromDom(o.target);if(ae("td")(n)||ae("th")(n)){const r=e.get(),s=t.get();ye(r,n)&&o.timeStamp-s<300&&(o.preventDefault(),i(n,n))}e.set(n),t.set(o.timeStamp)}}})();e.on("dragstart",(e=>{a.clearstate()})),e.on("mousedown",(e=>{d(e)&&Bm(e)&&a.mousedown(Nm(e))})),e.on("mouseover",(e=>{var t;void 0!==(t=e).buttons&&0==(1&t.buttons)||!Bm(e)||a.mouseover(Nm(e))})),e.on("mouseup",(e=>{d(e)&&Bm(e)&&a.mouseup(Nm(e))})),e.on("touchend",u.touchEnd),e.on("keyup",(t=>{const o=Nm(t);if(o.raw.shiftKey&&em(o.raw.which)){const t=e.selection.getRng(),n=pe.fromDom(t.startContainer),r=pe.fromDom(t.endContainer);c.keyup(o,n,t.startOffset,r,t.endOffset).each((e=>{m(o,e)}))}})),e.on("keydown",(o=>{const n=Nm(o);t.hide();const r=e.selection.getRng(),s=pe.fromDom(r.startContainer),l=pe.fromDom(r.endContainer),a=rn(tm,om)(pe.fromDom(e.selection.getStart()));c.keydown(n,s,r.startOffset,l,r.endOffset,a).each((e=>{m(n,e)})),t.show()})),e.on("NodeChange",(()=>{const t=e.selection,o=pe.fromDom(t.getStart()),r=pe.fromDom(t.getEnd());$r(Ft,[o,r]).fold((()=>n.clear(s)),f)}))})),e.on("PreInit",(()=>{e.serializer.addTempAttr(os.firstSelected),e.serializer.addTempAttr(os.lastSelected)})),{getSelectedCells:()=>((e,t,o,n)=>{switch(e.tag){case"none":return t();case"single":return(e=>[e.dom])(e.element);case"multiple":return(e=>E(e,(e=>e.dom)))(e.elements)}})(o.get(),g([])),clearSelectedCells:e=>n.clear(pe.fromDom(e))}},Am=e=>{let t=[];return{bind:e=>{if(void 0===e)throw new Error("Event bind error: undefined handler");t.push(e)},unbind:e=>{t=z(t,(t=>t!==e))},trigger:(...o)=>{const n={};N(e,((e,t)=>{n[e]=o[t]})),N(t,(e=>{e(n)}))}}},Wm=e=>({registry:K(e,(e=>({bind:e.bind,unbind:e.unbind}))),trigger:K(e,(e=>e.trigger))}),Lm=e=>e.slice(0).sort(),_m=(e,t)=>{const o=z(t,(t=>!D(e,t)));o.length>0&&(e=>{throw new Error("Unsupported keys for object: "+Lm(e).join(", "))})(o)},Mm=e=>((e,t)=>((e,t,o)=>{if(0===t.length)throw new Error("You must specify at least one required field.");return((e,t)=>{if(!l(t))throw new Error("The required fields must be an array. Was: "+t+".");N(t,(t=>{if(!r(t))throw new Error("The value "+t+" in the "+e+" fields was not a string.")}))})("required",t),(e=>{const t=Lm(e);L(t,((e,o)=>o{throw new Error("The field: "+e+" occurs more than once in the combined fields: ["+t.join(", ")+"].")}))})(t),n=>{const r=$(n);I(t,(e=>D(r,e)))||((e,t)=>{throw new Error("All required keys ("+Lm(e).join(", ")+") were not specified. Specified keys were: "+Lm(t).join(", ")+".")})(t,r),e(t,r);const s=z(t,(e=>!o.validate(n[e],e)));return s.length>0&&((e,t)=>{throw new Error("All values need to be of type: "+t+". Keys ("+Lm(e).join(", ")+") were not.")})(s,o.label),n}})(e,t,{validate:d,label:"function"}))(_m,e),jm=Mm(["compare","extract","mutate","sink"]),Im=Mm(["element","start","stop","destroy"]),Pm=Mm(["forceDrop","drop","move","delayDrop"]),Fm=()=>{const e=(()=>{const e=Wm({move:Am(["info"])});return{onEvent:f,reset:f,events:e.registry}})(),t=(()=>{let e=C.none();const t=Wm({move:Am(["info"])});return{onEvent:(o,n)=>{n.extract(o).each((o=>{const r=((t,o)=>{const n=e.map((e=>t.compare(e,o)));return e=C.some(o),n})(n,o);r.each((e=>{t.trigger.move(e)}))}))},reset:()=>{e=C.none()},events:t.registry}})();let o=e;return{on:()=>{o.reset(),o=t},off:()=>{o.reset(),o=e},isOn:()=>o===t,onEvent:(e,t)=>{o.onEvent(e,t)},events:t.events}},Hm=e=>{const t=e.replace(/\./g,"-");return{resolve:e=>t+"-"+e}},qm=Hm("ephox-dragster").resolve;var Vm=jm({compare:(e,t)=>dn(t.left-e.left,t.top-e.top),extract:e=>C.some(dn(e.x,e.y)),sink:(e,t)=>{const o=(e=>{const t={layerClass:qm("blocker"),...e},o=pe.fromTag("div");return ie(o,"role","presentation"),Tt(o,{position:"fixed",left:"0px",top:"0px",width:"100%",height:"100%"}),xm(o,qm("blocker")),xm(o,t.layerClass),{element:g(o),destroy:()=>{Ie(o)}}})(t),n=Em(o.element(),"mousedown",e.forceDrop),r=Em(o.element(),"mouseup",e.drop),s=Em(o.element(),"mousemove",e.move),l=Em(o.element(),"mouseout",e.delayDrop);return Im({element:o.element,start:e=>{We(e,o.element())},stop:()=>{Ie(o.element())},destroy:()=>{o.destroy(),r.unbind(),s.unbind(),l.unbind(),n.unbind()}})},mutate:(e,t)=>{e.mutate(t.left,t.top)}});const $m=Hm("ephox-snooker").resolve,Um=$m("resizer-bar"),Gm=$m("resizer-rows"),Km=$m("resizer-cols"),Ym=e=>{const t=st(e.parent(),"."+Um);N(t,Ie)},Jm=(e,t,o)=>{const n=e.origin();N(t,(t=>{t.each((t=>{const r=o(n,t);xm(r,Um),We(e.parent(),r)}))}))},Qm=(e,t,o,n,r)=>{const s=fn(o),l=t.isResizable,a=n.length>0?Rn.positions(n,o):[],c=a.length>0?((e,t)=>j(e.all,((e,o)=>t(e.element)?[o]:[])))(e,l):[];((e,t,o,n)=>{Jm(e,t,((e,t)=>{const r=((e,t,o,n,r)=>{const s=pe.fromTag("div");return Tt(s,{position:"absolute",left:t+"px",top:o-3.5+"px",height:"7px",width:n+"px"}),me(s,{"data-row":e,role:"presentation"}),s})(t.row,o.left-e.left,t.y-e.top,n);return xm(r,Gm),r}))})(t,z(a,((e,t)=>O(c,(e=>t===e)))),s,Eo(o));const i=r.length>0?On.positions(r,o):[],m=i.length>0?((e,t)=>{const o=[];return k(e.grid.columns,(n=>{en(e,n).map((e=>e.element)).forall(t)&&o.push(n)})),z(o,(o=>{const n=Jo(e,(e=>e.column===o));return I(n,(e=>t(e.element)))}))})(e,l):[];((e,t,o,n)=>{Jm(e,t,((e,t)=>{const r=((e,t,o,n,r)=>{const s=pe.fromTag("div");return Tt(s,{position:"absolute",left:t-3.5+"px",top:o+"px",height:r+"px",width:"7px"}),me(s,{"data-column":e,role:"presentation"}),s})(t.col,t.x-e.left,o.top-e.top,0,n);return xm(r,Km),r}))})(t,z(i,((e,t)=>O(m,(e=>t===e)))),s,cn(o))},Xm=(e,t)=>{if(Ym(e),e.isResizable(t)){const o=Uo(t),n=nn(o),r=tn(o);Qm(o,e,t,n,r)}},Zm=(e,t)=>{const o=st(e.parent(),"."+Um);N(o,t)},ed=e=>{Zm(e,(e=>{St(e,"display","none")}))},td=e=>{Zm(e,(e=>{St(e,"display","block")}))},od=$m("resizer-bar-dragging"),nd=e=>{const t=(()=>{const e=Wm({drag:Am(["xDelta","yDelta","target"])});let t=C.none();const o=(()=>{const e=Wm({drag:Am(["xDelta","yDelta"])});return{mutate:(t,o)=>{e.trigger.drag(t,o)},events:e.registry}})();return o.events.drag.bind((o=>{t.each((t=>{e.trigger.drag(o.xDelta,o.yDelta,t)}))})),{assign:e=>{t=C.some(e)},get:()=>t,mutate:o.mutate,events:e.registry}})(),o=((e,t={})=>{var o;return((e,t,o)=>{let n=!1;const r=Wm({start:Am([]),stop:Am([])}),s=Fm(),l=()=>{m.stop(),s.isOn()&&(s.off(),r.trigger.stop())},c=((e,t)=>{let o=null;const n=()=>{a(o)||(clearTimeout(o),o=null)};return{cancel:n,throttle:(...t)=>{n(),o=setTimeout((()=>{o=null,e.apply(null,t)}),200)}}})(l);s.events.move.bind((o=>{t.mutate(e,o.info)}));const i=e=>(...t)=>{n&&e.apply(null,t)},m=t.sink(Pm({forceDrop:l,drop:i(l),move:i((e=>{c.cancel(),s.onEvent(e,t)})),delayDrop:i(c.throttle)}),o);return{element:m.element,go:e=>{m.start(e),s.on(),r.trigger.start()},on:()=>{n=!0},off:()=>{n=!1},destroy:()=>{m.destroy()},events:r.registry}})(e,null!==(o=t.mode)&&void 0!==o?o:Vm,t)})(t,{});let n=C.none();const r=(e,t)=>C.from(de(e,t));t.events.drag.bind((e=>{r(e.target,"data-row").each((t=>{const o=At(e.target,"top");St(e.target,"top",o+e.yDelta+"px")})),r(e.target,"data-column").each((t=>{const o=At(e.target,"left");St(e.target,"left",o+e.xDelta+"px")}))}));const s=(e,t)=>At(e,t)-Et(e,"data-initial-"+t,0);o.events.stop.bind((()=>{t.get().each((t=>{n.each((o=>{r(t,"data-row").each((e=>{const n=s(t,"top");fe(t,"data-initial-top"),d.trigger.adjustHeight(o,n,parseInt(e,10))})),r(t,"data-column").each((e=>{const n=s(t,"left");fe(t,"data-initial-left"),d.trigger.adjustWidth(o,n,parseInt(e,10))})),Xm(e,o)}))}))}));const l=(n,r)=>{d.trigger.startAdjust(),t.assign(n),ie(n,"data-initial-"+r,At(n,r)),xm(n,od),St(n,"opacity","0.2"),o.go(e.parent())},c=Em(e.parent(),"mousedown",(e=>{var t;t=e.target,Cm(t,Gm)&&l(e.target,"top"),(e=>Cm(e,Km))(e.target)&&l(e.target,"left")})),i=t=>ye(t,e.view()),m=Em(e.view(),"mouseover",(t=>{var o;(o=t.target,dt(o,"table",i).filter(Is)).fold((()=>{et(t.target)&&Ym(e)}),(t=>{n=C.some(t),Xm(e,t)}))})),d=Wm({adjustHeight:Am(["table","delta","row"]),adjustWidth:Am(["table","delta","column"]),startAdjust:Am([])});return{destroy:()=>{c.unbind(),m.unbind(),o.destroy(),Ym(e)},refresh:t=>{Xm(e,t)},on:o.on,off:o.off,hideBars:w(ed,e),showBars:w(td,e),events:d.registry}},rd=(e,t,o)=>{const n=Rn,r=On,s=nd(e),l=Wm({beforeResize:Am(["table","type"]),afterResize:Am(["table","type"]),startDrag:Am([])});return s.events.adjustHeight.bind((e=>{const t=e.table;l.trigger.beforeResize(t,"row");((e,t,o,n)=>{const r=Uo(e),s=((e,t,o)=>Zn(e,t,o,Hn,(e=>e.getOrThunk(Lt))))(r,e,n),l=E(s,((e,n)=>o===n?Math.max(t+e,Lt()):e)),a=Ol(r,l),c=((e,t)=>E(e.all,((e,o)=>({element:e.element,height:t[o]}))))(r,l);N(c,(e=>{_n(e.element,e.height)})),N(a,(e=>{_n(e.element,e.height)}));const i=A(l,((e,t)=>e+t),0);_n(e,i)})(t,n.delta(e.delta,t),e.row,n),l.trigger.afterResize(t,"row")})),s.events.startAdjust.bind((e=>{l.trigger.startDrag()})),s.events.adjustWidth.bind((e=>{const n=e.table;l.trigger.beforeResize(n,"col");const s=r.delta(e.delta,n),a=o(n);El(n,s,e.column,t,a),l.trigger.afterResize(n,"col")})),{on:s.on,off:s.off,refreshBars:s.refresh,hideBars:s.hideBars,showBars:s.showBars,destroy:s.destroy,events:l.registry}},sd=e=>m(e)&&"TABLE"===e.nodeName,ld="bar-",ad=e=>"false"!==de(e,"data-mce-resize"),cd=e=>{const t=Gi(),o=Gi(),n=Gi();let r,s;const l=t=>ec(e,t),a=()=>Va(e)?Cs():xs();return e.on("init",(()=>{const r=((e,t)=>e.inline?((e,t,o)=>({parent:g(t),view:g(e),origin:g(dn(0,0)),isResizable:o}))(pe.fromDom(e.getBody()),(()=>{const e=pe.fromTag("div");return Tt(e,{position:"static",height:"0",width:"0",padding:"0",margin:"0",border:"0"}),We(tt(pe.fromDom(document)),e),e})(),t):((e,t)=>{const o=se(e)?(e=>pe.fromDom(Te(e).dom.documentElement))(e):e;return{parent:g(o),view:g(e),origin:g(dn(0,0)),isResizable:t}})(pe.fromDom(e.getDoc()),t))(e,ad);if(n.set(r),(e=>{const t=e.options.get("object_resizing");return D(t.split(","),"table")})(e)&&Ja(e)){const n=a(),s=rd(r,n,l);s.on(),s.events.startDrag.bind((o=>{t.set(e.selection.getRng())})),s.events.beforeResize.bind((t=>{const o=t.table.dom;((e,t,o,n,r)=>{e.dispatch("ObjectResizeStart",{target:t,width:o,height:n,origin:r})})(e,o,Nr(o),Br(o),ld+t.type)})),s.events.afterResize.bind((o=>{const n=o.table,r=n.dom;kr(n),t.on((t=>{e.selection.setRng(t),e.focus()})),((e,t,o,n,r)=>{e.dispatch("ObjectResized",{target:t,width:o,height:n,origin:r})})(e,r,Nr(r),Br(r),ld+o.type),e.undoManager.add()})),o.set(s)}})),e.on("ObjectResizeStart",(t=>{const o=t.target;if(sd(o)){const n=pe.fromDom(o);N(e.dom.select(".mce-clonedresizable"),(t=>{e.dom.addClass(t,"mce-"+qa(e)+"-columns")})),!hc(n)&&Ka(e)?vc(n):!gc(n)&&Ga(e)&&bc(n),pc(n)&&wt(t.origin,ld)&&bc(n),r=t.width,s=Ya(e)?"":((e,t)=>{const o=e.dom.getStyle(t,"width")||e.dom.getAttrib(t,"width");return C.from(o).filter(yt)})(e,o).getOr("")}})),e.on("ObjectResized",(t=>{const o=t.target;if(sd(o)){const n=pe.fromDom(o),c=t.origin;wt(c,"corner-")&&((t,o,n)=>{const c=bt(o,"e");if(""===s&&bc(t),n!==r&&""!==s){St(t,"width",s);const o=a(),i=l(t),m=Va(e)||c?(e=>Ss(e).columns)(t)-1:0;El(t,n-r,m,o,i)}else if((e=>/^(\d+(\.\d+)?)%$/.test(e))(s)){const e=parseFloat(s.replace("%",""));St(t,"width",n*e/r+"%")}(e=>/^(\d+(\.\d+)?)px$/.test(e))(s)&&(e=>{const t=Uo(e);Zo(t)||N(It(e),(e=>{const t=Rt(e,"width");St(e,"width",t),fe(e,"width")}))})(t)})(n,c,t.width),kr(n),Wa(e,n.dom,La)}})),e.on("SwitchMode",(()=>{o.on((t=>{e.mode.isReadOnly()?t.hideBars():t.showBars()}))})),e.on("remove",(()=>{o.on((e=>{e.destroy()})),n.on((t=>{((e,t)=>{e.inline&&Ie(t.parent())})(e,t)}))})),{refresh:e=>{o.on((t=>t.refreshBars(pe.fromDom(e))))},hide:()=>{o.on((e=>e.hideBars()))},show:()=>{o.on((e=>e.showBars()))}}},id=e=>{(e=>{const t=e.options.register;t("table_clone_elements",{processor:"string[]"}),t("table_use_colgroups",{processor:"boolean",default:!0}),t("table_header_type",{processor:e=>{const t=D(["section","cells","sectionCells","auto"],e);return t?{value:e,valid:t}:{valid:!1,message:"Must be one of: section, cells, sectionCells or auto."}},default:"section"}),t("table_sizing_mode",{processor:"string",default:"auto"}),t("table_default_attributes",{processor:"object",default:{border:"1"}}),t("table_default_styles",{processor:"object",default:{"border-collapse":"collapse"}}),t("table_column_resizing",{processor:e=>{const t=D(["preservetable","resizetable"],e);return t?{value:e,valid:t}:{valid:!1,message:"Must be preservetable, or resizetable."}},default:"preservetable"}),t("table_resize_bars",{processor:"boolean",default:!0}),t("table_style_by_css",{processor:"boolean",default:!0})})(e);const t=cd(e),o=zm(e,t),n=tc(e,t,o);return Ic(e,n),((e,t)=>{const o=Or(e),n=t=>ls(Er(e)).bind((n=>Ft(n,o).map((o=>{const r=ns(as(e),o,n);return t(o,r)})))).getOr("");G({mceTableRowType:()=>n(t.getTableRowType),mceTableCellType:()=>n(t.getTableCellType),mceTableColType:()=>n(t.getTableColType)},((t,o)=>e.addQueryValueHandler(o,t)))})(e,n),cs(e,n),{getSelectedCells:o.getSelectedCells,clearSelectedCells:o.clearSelectedCells}};e.add("dom",(e=>({table:id(e)})))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/advlist/plugin.min.js b/public/plugins/tinymce/plugins/advlist/plugin.min.js new file mode 100644 index 000000000..14f123a06 --- /dev/null +++ b/public/plugins/tinymce/plugins/advlist/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=(t,e,r)=>{const s="UL"===e?"InsertUnorderedList":"InsertOrderedList";t.execCommand(s,!1,!1===r?null:{"list-style-type":r})},r=t=>e=>e.options.get(t),s=r("advlist_number_styles"),n=r("advlist_bullet_styles"),l=t=>null==t,i=t=>!l(t);var o=tinymce.util.Tools.resolve("tinymce.util.Tools");class a{constructor(t,e){this.tag=t,this.value=e}static some(t){return new a(!0,t)}static none(){return a.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?a.some(t(this.value)):a.none()}bind(t){return this.tag?t(this.value):a.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:a.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return i(t)?a.some(t):a.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}a.singletonNone=new a(!1);const u=t=>i(t)&&/^(TH|TD)$/.test(t.nodeName),d=t=>l(t)||"default"===t?"":t,g=(t,e)=>r=>{const s=s=>{r.setActive(((t,e,r)=>{const s=((t,e)=>{for(let r=0;re=>i(e)&&/^(OL|UL|DL)$/.test(e.nodeName)&&((t,e)=>t.dom.isChildOf(e,t.getBody()))(t,e))(t));return l.length>0&&l[0].nodeName===r})(t,s,e)),r.setEnabled(!((t,e)=>{const r=t.dom.getParent(e,"ol,ul,dl");return((t,e)=>null!==e&&"false"===t.dom.getContentEditableParent(e))(t,r)})(t,s.element))};return t.on("NodeChange",s),()=>t.off("NodeChange",s)},h=(t,r,s,n,l,i)=>{i.length>1?((t,r,s,n,l,i)=>{t.ui.registry.addSplitButton(r,{tooltip:s,icon:"OL"===l?"ordered-list":"unordered-list",presets:"listpreview",columns:3,fetch:t=>{t(o.map(i,(t=>{const e="OL"===l?"num":"bull",r="disc"===t||"decimal"===t?"default":t,s=d(t),n=(t=>t.replace(/\-/g," ").replace(/\b\w/g,(t=>t.toUpperCase())))(t);return{type:"choiceitem",value:s,icon:"list-"+e+"-"+r,text:n}})))},onAction:()=>t.execCommand(n),onItemAction:(r,s)=>{e(t,l,s)},select:e=>{const r=(t=>{const e=t.dom.getParent(t.selection.getNode(),"ol,ul"),r=t.dom.getStyle(e,"listStyleType");return a.from(r)})(t);return r.map((t=>e===t)).getOr(!1)},onSetup:g(t,l)})})(t,r,s,n,l,i):((t,r,s,n,l,i)=>{t.ui.registry.addToggleButton(r,{active:!1,tooltip:s,icon:"OL"===l?"ordered-list":"unordered-list",onSetup:g(t,l),onAction:()=>t.queryCommandState(n)||""===i?t.execCommand(n):e(t,l,i)})})(t,r,s,n,l,d(i[0]))};t.add("advlist",(t=>{t.hasPlugin("lists")?((t=>{const e=t.options.register;e("advlist_number_styles",{processor:"string[]",default:"default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman".split(",")}),e("advlist_bullet_styles",{processor:"string[]",default:"default,circle,square".split(",")})})(t),(t=>{h(t,"numlist","Numbered list","InsertOrderedList","OL",s(t)),h(t,"bullist","Bullet list","InsertUnorderedList","UL",n(t))})(t),(t=>{t.addCommand("ApplyUnorderedListStyle",((r,s)=>{e(t,"UL",s["list-style-type"])})),t.addCommand("ApplyOrderedListStyle",((r,s)=>{e(t,"OL",s["list-style-type"])}))})(t)):console.error("Please use the Lists plugin together with the Advanced List plugin.")}))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/anchor/plugin.min.js b/public/plugins/tinymce/plugins/anchor/plugin.min.js new file mode 100644 index 000000000..9de80375d --- /dev/null +++ b/public/plugins/tinymce/plugins/anchor/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.dom.RangeUtils"),o=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=("allow_html_in_named_anchor",e=>e.options.get("allow_html_in_named_anchor"));const a="a:not([href])",r=e=>!e,i=e=>e.getAttribute("id")||e.getAttribute("name")||"",l=e=>(e=>"a"===e.nodeName.toLowerCase())(e)&&!e.getAttribute("href")&&""!==i(e),s=e=>e.dom.getParent(e.selection.getStart(),a),d=(e,a)=>{const r=s(e);r?((e,t,o)=>{o.removeAttribute("name"),o.id=t,e.addVisual(),e.undoManager.add()})(e,a,r):((e,a)=>{e.undoManager.transact((()=>{n(e)||e.selection.collapse(!0),e.selection.isCollapsed()?e.insertContent(e.dom.createHTML("a",{id:a})):((e=>{const n=e.dom;t(n).walk(e.selection.getRng(),(e=>{o.each(e,(e=>{var t;l(t=e)&&!t.firstChild&&n.remove(e,!1)}))}))})(e),e.formatter.remove("namedAnchor",void 0,void 0,!0),e.formatter.apply("namedAnchor",{value:a}),e.addVisual())}))})(e,a),e.focus()},c=e=>(e=>r(e.attr("href"))&&!r(e.attr("id")||e.attr("name")))(e)&&!e.firstChild,m=e=>t=>{for(let o=0;o{(e=>{(0,e.options.register)("allow_html_in_named_anchor",{processor:"boolean",default:!1})})(e),(e=>{e.on("PreInit",(()=>{e.parser.addNodeFilter("a",m("false")),e.serializer.addNodeFilter("a",m(null))}))})(e),(e=>{e.addCommand("mceAnchor",(()=>{(e=>{const t=(e=>{const t=s(e);return t?i(t):""})(e);e.windowManager.open({title:"Anchor",size:"normal",body:{type:"panel",items:[{name:"id",type:"input",label:"ID",placeholder:"example"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{id:t},onSubmit:t=>{((e,t)=>/^[A-Za-z][A-Za-z0-9\-:._]*$/.test(t)?(d(e,t),!0):(e.windowManager.alert("ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores."),!1))(e,t.getData().id)&&t.close()}})})(e)}))})(e),(e=>{const t=()=>e.execCommand("mceAnchor");e.ui.registry.addToggleButton("anchor",{icon:"bookmark",tooltip:"Anchor",onAction:t,onSetup:t=>e.selection.selectorChangedWithUnbind("a:not([href])",t.setActive).unbind}),e.ui.registry.addMenuItem("anchor",{icon:"bookmark",text:"Anchor...",onAction:t})})(e),e.on("PreInit",(()=>{(e=>{e.formatter.register("namedAnchor",{inline:"a",selector:a,remove:"all",split:!0,deep:!0,attributes:{id:"%value"},onmatch:(e,t,o)=>l(e)})})(e)}))}))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/autolink/plugin.min.js b/public/plugins/tinymce/plugins/autolink/plugin.min.js new file mode 100644 index 000000000..3202433aa --- /dev/null +++ b/public/plugins/tinymce/plugins/autolink/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>t.options.get(e),n=t("autolink_pattern"),o=t("link_default_target"),r=t("link_default_protocol"),a=t("allow_unsafe_link_target"),s=("string",e=>"string"===(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=o=e,(r=String).prototype.isPrototypeOf(n)||(null===(a=o.constructor)||void 0===a?void 0:a.name)===r.name)?"string":t;var n,o,r,a})(e));const l=(void 0,e=>undefined===e);const i=e=>!(e=>null==e)(e),c=Object.hasOwnProperty,d=e=>"\ufeff"===e;var u=tinymce.util.Tools.resolve("tinymce.dom.TextSeeker");const f=e=>/^[(\[{ \u00a0]$/.test(e),g=(e,t,n)=>{for(let o=t-1;o>=0;o--){const t=e.charAt(o);if(!d(t)&&n(t))return o}return-1},m=(e,t)=>{var o;const a=e.schema.getVoidElements(),s=n(e),{dom:i,selection:d}=e;if(null!==i.getParent(d.getNode(),"a[href]"))return null;const m=d.getRng(),k=u(i,(e=>{return i.isBlock(e)||(t=a,n=e.nodeName.toLowerCase(),c.call(t,n))||"false"===i.getContentEditable(e);var t,n})),{container:p,offset:y}=((e,t)=>{let n=e,o=t;for(;1===n.nodeType&&n.childNodes[o];)n=n.childNodes[o],o=3===n.nodeType?n.data.length:n.childNodes.length;return{container:n,offset:o}})(m.endContainer,m.endOffset),h=null!==(o=i.getParent(p,i.isBlock))&&void 0!==o?o:i.getRoot(),w=k.backwards(p,y+t,((e,t)=>{const n=e.data,o=g(n,t,(r=f,e=>!r(e)));var r,a;return-1===o||(a=n[o],/[?!,.;:]/.test(a))?o:o+1}),h);if(!w)return null;let v=w.container;const _=k.backwards(w.container,w.offset,((e,t)=>{v=e;const n=g(e.data,t,f);return-1===n?n:n+1}),h),A=i.createRng();_?A.setStart(_.container,_.offset):A.setStart(v,0),A.setEnd(w.container,w.offset);const C=A.toString().replace(/\uFEFF/g,"").match(s);if(C){let t=C[0];return $="www.",(b=t).length>=$.length&&b.substr(0,0+$.length)===$?t=r(e)+"://"+t:((e,t,n=0,o)=>{const r=e.indexOf(t,n);return-1!==r&&(!!l(o)||r+t.length<=o)})(t,"@")&&!(e=>/^([A-Za-z][A-Za-z\d.+-]*:\/\/)|mailto:/.test(e))(t)&&(t="mailto:"+t),{rng:A,url:t}}var b,$;return null},k=(e,t)=>{const{dom:n,selection:r}=e,{rng:l,url:i}=t,c=r.getBookmark();r.setRng(l);const d="createlink",u={command:d,ui:!1,value:i};if(!e.dispatch("BeforeExecCommand",u).isDefaultPrevented()){e.getDoc().execCommand(d,!1,i),e.dispatch("ExecCommand",u);const t=o(e);if(s(t)){const o=r.getNode();n.setAttrib(o,"target",t),"_blank"!==t||a(e)||n.setAttrib(o,"rel","noopener")}}r.moveToBookmark(c),e.nodeChanged()},p=e=>{const t=m(e,-1);i(t)&&k(e,t)},y=p;e.add("autolink",(e=>{(e=>{const t=e.options.register;t("autolink_pattern",{processor:"regexp",default:new RegExp("^"+/(?:[A-Za-z][A-Za-z\d.+-]{0,14}:\/\/(?:[-.~*+=!&;:'%@?^${}(),\w]+@)?|www\.|[-;:&=+$,.\w]+@)[A-Za-z\d-]+(?:\.[A-Za-z\d-]+)*(?::\d+)?(?:\/(?:[-.~*+=!;:'%@$(),\/\w]*[-~*+=%@$()\/\w])?)?(?:\?(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?(?:#(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?/g.source+"$","i")}),t("link_default_target",{processor:"string"}),t("link_default_protocol",{processor:"string",default:"https"})})(e),(e=>{e.on("keydown",(t=>{13!==t.keyCode||t.isDefaultPrevented()||(e=>{const t=m(e,0);i(t)&&k(e,t)})(e)})),e.on("keyup",(t=>{32===t.keyCode?p(e):(48===t.keyCode&&t.shiftKey||221===t.keyCode)&&y(e)}))})(e)}))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/autoresize/plugin.min.js b/public/plugins/tinymce/plugins/autoresize/plugin.min.js new file mode 100644 index 000000000..7559e9f9a --- /dev/null +++ b/public/plugins/tinymce/plugins/autoresize/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.Env");const o=e=>t=>t.options.get(e),n=o("min_height"),s=o("max_height"),i=o("autoresize_overflow_padding"),r=o("autoresize_bottom_margin"),l=(e,t)=>{const o=e.getBody();o&&(o.style.overflowY=t?"":"hidden",t||(o.scrollTop=0))},a=(e,t,o,n)=>{var s;const i=parseInt(null!==(s=e.getStyle(t,o,n))&&void 0!==s?s:"",10);return isNaN(i)?0:i},g=(e,o,i)=>{var c;const u=e.dom,d=e.getDoc();if(!d)return;if((e=>e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen())(e))return void l(e,!0);const f=d.documentElement,m=r(e),p=null!==(c=n(e))&&void 0!==c?c:e.getElement().offsetHeight;let h=p;const v=a(u,f,"margin-top",!0),y=a(u,f,"margin-bottom",!0);let C=f.offsetHeight+v+y+m;C<0&&(C=0);const S=e.getContainer().offsetHeight-e.getContentAreaContainer().offsetHeight;C+S>p&&(h=C+S);const z=s(e);if(z&&h>z?(h=z,l(e,!0)):l(e,!1),h!==o.get()){const n=h-o.get();if(u.setStyle(e.getContainer(),"height",h+"px"),o.set(h),(e=>{e.dispatch("ResizeEditor")})(e),t.browser.isSafari()&&(t.os.isMacOS()||t.os.isiOS())){const t=e.getWin();t.scrollTo(t.pageXOffset,t.pageYOffset)}e.hasFocus()&&(e=>{if("setcontent"===(null==e?void 0:e.type.toLowerCase())){const t=e;return!0===t.selection||!0===t.paste}return!1})(i)&&e.selection.scrollIntoView(),(t.browser.isSafari()||t.browser.isChromium())&&n<0&&g(e,o,i)}};e.add("autoresize",(e=>{if((e=>{const t=e.options.register;t("autoresize_overflow_padding",{processor:"number",default:1}),t("autoresize_bottom_margin",{processor:"number",default:50})})(e),e.options.isSet("resize")||e.options.set("resize",!1),!e.inline){const t=(e=>{let t=0;return{get:()=>t,set:e=>{t=e}}})();((e,t)=>{e.addCommand("mceAutoResize",(()=>{g(e,t)}))})(e,t),((e,t)=>{e.on("init",(()=>{const t=i(e),o=e.dom;o.setStyles(e.getDoc().documentElement,{height:"auto"}),o.setStyles(e.getBody(),{paddingLeft:t,paddingRight:t,"min-height":0})})),e.on("NodeChange SetContent keyup FullscreenStateChanged ResizeContent",(o=>{g(e,t,o)}))})(e,t)}}))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/autosave/plugin.min.js b/public/plugins/tinymce/plugins/autosave/plugin.min.js new file mode 100644 index 000000000..585c8ef8b --- /dev/null +++ b/public/plugins/tinymce/plugins/autosave/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=("string",t=>"string"===(t=>{const e=typeof t;return null===t?"null":"object"===e&&Array.isArray(t)?"array":"object"===e&&(r=o=t,(a=String).prototype.isPrototypeOf(r)||(null===(s=o.constructor)||void 0===s?void 0:s.name)===a.name)?"string":e;var r,o,a,s})(t));const r=(void 0,t=>undefined===t);var o=tinymce.util.Tools.resolve("tinymce.util.Delay"),a=tinymce.util.Tools.resolve("tinymce.util.LocalStorage"),s=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=t=>{const e=/^(\d+)([ms]?)$/.exec(t);return(e&&e[2]?{s:1e3,m:6e4}[e[2]]:1)*parseInt(t,10)},i=t=>e=>e.options.get(t),u=i("autosave_ask_before_unload"),l=i("autosave_restore_when_empty"),c=i("autosave_interval"),d=i("autosave_retention"),m=t=>{const e=document.location;return t.options.get("autosave_prefix").replace(/{path}/g,e.pathname).replace(/{query}/g,e.search).replace(/{hash}/g,e.hash).replace(/{id}/g,t.id)},v=(t,e)=>{if(r(e))return t.dom.isEmpty(t.getBody());{const r=s.trim(e);if(""===r)return!0;{const e=(new DOMParser).parseFromString(r,"text/html");return t.dom.isEmpty(e)}}},f=t=>{var e;const r=parseInt(null!==(e=a.getItem(m(t)+"time"))&&void 0!==e?e:"0",10)||0;return!((new Date).getTime()-r>d(t)&&(p(t,!1),1))},p=(t,e)=>{const r=m(t);a.removeItem(r+"draft"),a.removeItem(r+"time"),!1!==e&&(t=>{t.dispatch("RemoveDraft")})(t)},g=t=>{const e=m(t);!v(t)&&t.isDirty()&&(a.setItem(e+"draft",t.getContent({format:"raw",no_events:!0})),a.setItem(e+"time",(new Date).getTime().toString()),(t=>{t.dispatch("StoreDraft")})(t))},y=t=>{var e;const r=m(t);f(t)&&(t.setContent(null!==(e=a.getItem(r+"draft"))&&void 0!==e?e:"",{format:"raw"}),(t=>{t.dispatch("RestoreDraft")})(t))};var D=tinymce.util.Tools.resolve("tinymce.EditorManager");const h=t=>e=>{e.setEnabled(f(t));const r=()=>e.setEnabled(f(t));return t.on("StoreDraft RestoreDraft RemoveDraft",r),()=>t.off("StoreDraft RestoreDraft RemoveDraft",r)};t.add("autosave",(t=>((t=>{const r=t.options.register,o=t=>{const r=e(t);return r?{value:n(t),valid:r}:{valid:!1,message:"Must be a string."}};r("autosave_ask_before_unload",{processor:"boolean",default:!0}),r("autosave_prefix",{processor:"string",default:"tinymce-autosave-{path}{query}{hash}-{id}-"}),r("autosave_restore_when_empty",{processor:"boolean",default:!1}),r("autosave_interval",{processor:o,default:"30s"}),r("autosave_retention",{processor:o,default:"20m"})})(t),(t=>{t.editorManager.on("BeforeUnload",(t=>{let e;s.each(D.get(),(t=>{t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&u(t)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))})),e&&(t.preventDefault(),t.returnValue=e)}))})(t),(t=>{(t=>{const e=c(t);o.setEditorInterval(t,(()=>{g(t)}),e)})(t);const e=()=>{(t=>{t.undoManager.transact((()=>{y(t),p(t)})),t.focus()})(t)};t.ui.registry.addButton("restoredraft",{tooltip:"Restore last draft",icon:"restore-draft",onAction:e,onSetup:h(t)}),t.ui.registry.addMenuItem("restoredraft",{text:"Restore last draft",icon:"restore-draft",onAction:e,onSetup:h(t)})})(t),t.on("init",(()=>{l(t)&&t.dom.isEmpty(t.getBody())&&y(t)})),(t=>({hasDraft:()=>f(t),storeDraft:()=>g(t),restoreDraft:()=>y(t),removeDraft:e=>p(t,e),isEmpty:e=>v(t,e)}))(t))))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/charmap/plugin.min.js b/public/plugins/tinymce/plugins/charmap/plugin.min.js new file mode 100644 index 000000000..12108e836 --- /dev/null +++ b/public/plugins/tinymce/plugins/charmap/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=(e,t)=>{const r=((e,t)=>e.dispatch("insertCustomChar",{chr:t}))(e,t).chr;e.execCommand("mceInsertContent",!1,r)},r=e=>t=>e===t,a=("array",e=>"array"===(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(r=a=e,(n=String).prototype.isPrototypeOf(r)||(null===(i=a.constructor)||void 0===i?void 0:i.name)===n.name)?"string":t;var r,a,n,i})(e));const n=r(null),i=r(void 0),o=e=>"function"==typeof e,s=(!1,()=>false);class l{constructor(e,t){this.tag=e,this.value=t}static some(e){return new l(!0,e)}static none(){return l.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?l.some(e(this.value)):l.none()}bind(e){return this.tag?e(this.value):l.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:l.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return null==e?l.none():l.some(e)}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}l.singletonNone=new l(!1);const c=Array.prototype.push,u=(e,t)=>{const r=e.length,a=new Array(r);for(let n=0;nt=>t.options.get(e),m=h("charmap"),p=h("charmap_append"),d=g.isArray,f="User Defined",y=e=>{return d(e)?(t=e,g.grep(t,(e=>d(e)&&2===e.length))):"function"==typeof e?e():[];var t},w=e=>{const t=((e,t)=>{const r=m(e);r&&(t=[{name:f,characters:y(r)}]);const a=p(e);if(a){const e=g.grep(t,(e=>e.name===f));return e.length?(e[0].characters=[...e[0].characters,...y(a)],t):t.concat({name:f,characters:y(a)})}return t})(e,[{name:"Currency",characters:[[36,"dollar sign"],[162,"cent sign"],[8364,"euro sign"],[163,"pound sign"],[165,"yen sign"],[164,"currency sign"],[8352,"euro-currency sign"],[8353,"colon sign"],[8354,"cruzeiro sign"],[8355,"french franc sign"],[8356,"lira sign"],[8357,"mill sign"],[8358,"naira sign"],[8359,"peseta sign"],[8360,"rupee sign"],[8361,"won sign"],[8362,"new sheqel sign"],[8363,"dong sign"],[8365,"kip sign"],[8366,"tugrik sign"],[8367,"drachma sign"],[8368,"german penny symbol"],[8369,"peso sign"],[8370,"guarani sign"],[8371,"austral sign"],[8372,"hryvnia sign"],[8373,"cedi sign"],[8374,"livre tournois sign"],[8375,"spesmilo sign"],[8376,"tenge sign"],[8377,"indian rupee sign"],[8378,"turkish lira sign"],[8379,"nordic mark sign"],[8380,"manat sign"],[8381,"ruble sign"],[20870,"yen character"],[20803,"yuan character"],[22291,"yuan character, in hong kong and taiwan"],[22278,"yen/yuan character variant one"]]},{name:"Text",characters:[[169,"copyright sign"],[174,"registered sign"],[8482,"trade mark sign"],[8240,"per mille sign"],[181,"micro sign"],[183,"middle dot"],[8226,"bullet"],[8230,"three dot leader"],[8242,"minutes / feet"],[8243,"seconds / inches"],[167,"section sign"],[182,"paragraph sign"],[223,"sharp s / ess-zed"]]},{name:"Quotations",characters:[[8249,"single left-pointing angle quotation mark"],[8250,"single right-pointing angle quotation mark"],[171,"left pointing guillemet"],[187,"right pointing guillemet"],[8216,"left single quotation mark"],[8217,"right single quotation mark"],[8220,"left double quotation mark"],[8221,"right double quotation mark"],[8218,"single low-9 quotation mark"],[8222,"double low-9 quotation mark"],[60,"less-than sign"],[62,"greater-than sign"],[8804,"less-than or equal to"],[8805,"greater-than or equal to"],[8211,"en dash"],[8212,"em dash"],[175,"macron"],[8254,"overline"],[164,"currency sign"],[166,"broken bar"],[168,"diaeresis"],[161,"inverted exclamation mark"],[191,"turned question mark"],[710,"circumflex accent"],[732,"small tilde"],[176,"degree sign"],[8722,"minus sign"],[177,"plus-minus sign"],[247,"division sign"],[8260,"fraction slash"],[215,"multiplication sign"],[185,"superscript one"],[178,"superscript two"],[179,"superscript three"],[188,"fraction one quarter"],[189,"fraction one half"],[190,"fraction three quarters"]]},{name:"Mathematical",characters:[[402,"function / florin"],[8747,"integral"],[8721,"n-ary sumation"],[8734,"infinity"],[8730,"square root"],[8764,"similar to"],[8773,"approximately equal to"],[8776,"almost equal to"],[8800,"not equal to"],[8801,"identical to"],[8712,"element of"],[8713,"not an element of"],[8715,"contains as member"],[8719,"n-ary product"],[8743,"logical and"],[8744,"logical or"],[172,"not sign"],[8745,"intersection"],[8746,"union"],[8706,"partial differential"],[8704,"for all"],[8707,"there exists"],[8709,"diameter"],[8711,"backward difference"],[8727,"asterisk operator"],[8733,"proportional to"],[8736,"angle"]]},{name:"Extended Latin",characters:[[192,"A - grave"],[193,"A - acute"],[194,"A - circumflex"],[195,"A - tilde"],[196,"A - diaeresis"],[197,"A - ring above"],[256,"A - macron"],[198,"ligature AE"],[199,"C - cedilla"],[200,"E - grave"],[201,"E - acute"],[202,"E - circumflex"],[203,"E - diaeresis"],[274,"E - macron"],[204,"I - grave"],[205,"I - acute"],[206,"I - circumflex"],[207,"I - diaeresis"],[298,"I - macron"],[208,"ETH"],[209,"N - tilde"],[210,"O - grave"],[211,"O - acute"],[212,"O - circumflex"],[213,"O - tilde"],[214,"O - diaeresis"],[216,"O - slash"],[332,"O - macron"],[338,"ligature OE"],[352,"S - caron"],[217,"U - grave"],[218,"U - acute"],[219,"U - circumflex"],[220,"U - diaeresis"],[362,"U - macron"],[221,"Y - acute"],[376,"Y - diaeresis"],[562,"Y - macron"],[222,"THORN"],[224,"a - grave"],[225,"a - acute"],[226,"a - circumflex"],[227,"a - tilde"],[228,"a - diaeresis"],[229,"a - ring above"],[257,"a - macron"],[230,"ligature ae"],[231,"c - cedilla"],[232,"e - grave"],[233,"e - acute"],[234,"e - circumflex"],[235,"e - diaeresis"],[275,"e - macron"],[236,"i - grave"],[237,"i - acute"],[238,"i - circumflex"],[239,"i - diaeresis"],[299,"i - macron"],[240,"eth"],[241,"n - tilde"],[242,"o - grave"],[243,"o - acute"],[244,"o - circumflex"],[245,"o - tilde"],[246,"o - diaeresis"],[248,"o slash"],[333,"o macron"],[339,"ligature oe"],[353,"s - caron"],[249,"u - grave"],[250,"u - acute"],[251,"u - circumflex"],[252,"u - diaeresis"],[363,"u - macron"],[253,"y - acute"],[254,"thorn"],[255,"y - diaeresis"],[563,"y - macron"],[913,"Alpha"],[914,"Beta"],[915,"Gamma"],[916,"Delta"],[917,"Epsilon"],[918,"Zeta"],[919,"Eta"],[920,"Theta"],[921,"Iota"],[922,"Kappa"],[923,"Lambda"],[924,"Mu"],[925,"Nu"],[926,"Xi"],[927,"Omicron"],[928,"Pi"],[929,"Rho"],[931,"Sigma"],[932,"Tau"],[933,"Upsilon"],[934,"Phi"],[935,"Chi"],[936,"Psi"],[937,"Omega"],[945,"alpha"],[946,"beta"],[947,"gamma"],[948,"delta"],[949,"epsilon"],[950,"zeta"],[951,"eta"],[952,"theta"],[953,"iota"],[954,"kappa"],[955,"lambda"],[956,"mu"],[957,"nu"],[958,"xi"],[959,"omicron"],[960,"pi"],[961,"rho"],[962,"final sigma"],[963,"sigma"],[964,"tau"],[965,"upsilon"],[966,"phi"],[967,"chi"],[968,"psi"],[969,"omega"]]},{name:"Symbols",characters:[[8501,"alef symbol"],[982,"pi symbol"],[8476,"real part symbol"],[978,"upsilon - hook symbol"],[8472,"Weierstrass p"],[8465,"imaginary part"]]},{name:"Arrows",characters:[[8592,"leftwards arrow"],[8593,"upwards arrow"],[8594,"rightwards arrow"],[8595,"downwards arrow"],[8596,"left right arrow"],[8629,"carriage return"],[8656,"leftwards double arrow"],[8657,"upwards double arrow"],[8658,"rightwards double arrow"],[8659,"downwards double arrow"],[8660,"left right double arrow"],[8756,"therefore"],[8834,"subset of"],[8835,"superset of"],[8836,"not a subset of"],[8838,"subset of or equal to"],[8839,"superset of or equal to"],[8853,"circled plus"],[8855,"circled times"],[8869,"perpendicular"],[8901,"dot operator"],[8968,"left ceiling"],[8969,"right ceiling"],[8970,"left floor"],[8971,"right floor"],[9001,"left-pointing angle bracket"],[9002,"right-pointing angle bracket"],[9674,"lozenge"],[9824,"black spade suit"],[9827,"black club suit"],[9829,"black heart suit"],[9830,"black diamond suit"],[8194,"en space"],[8195,"em space"],[8201,"thin space"],[8204,"zero width non-joiner"],[8205,"zero width joiner"],[8206,"left-to-right mark"],[8207,"right-to-left mark"]]}]);return t.length>1?[{name:"All",characters:(r=t,n=e=>e.characters,(e=>{const t=[];for(let r=0,n=e.length;r{let t=e;return{get:()=>t,set:e=>{t=e}}},b=(e,t,r=0,a)=>{const n=e.indexOf(t,r);return-1!==n&&(!!i(a)||n+t.length<=a)},k=String.fromCodePoint,C=(e,t)=>{const r=[],a=t.toLowerCase();return((e,t)=>{for(let t=0,i=e.length;t!!b(k(e).toLowerCase(),r)||b(t.toLowerCase(),r)||b(t.toLowerCase().replace(/\s+/g,""),r))((n=e[t])[0],n[1],a)&&r.push(n);var n})(e.characters),u(r,(e=>({text:e[1],value:k(e[0]),icon:k(e[0])})))},x="pattern",A=(e,r)=>{const a=()=>[{label:"Search",type:"input",name:x},{type:"collection",name:"results"}],i=1===r.length?v(f):v("All"),o=((e,t)=>{let r=null;const a=()=>{n(r)||(clearTimeout(r),r=null)};return{cancel:a,throttle:(...t)=>{a(),r=setTimeout((()=>{r=null,e.apply(null,t)}),40)}}})((e=>{const t=e.getData().pattern;((e,t)=>{var a,n;(a=r,n=e=>e.name===i.get(),((e,t,r)=>{for(let a=0,n=e.length;a{const a=C(r,t);e.setData({results:a})}))})(e,t)})),c={title:"Special Character",size:"normal",body:1===r.length?{type:"panel",items:a()}:{type:"tabpanel",tabs:u(r,(e=>({title:e.name,name:e.name,items:a()})))},buttons:[{type:"cancel",name:"close",text:"Close",primary:!0}],initialData:{pattern:"",results:C(r[0],"")},onAction:(r,a)=>{"results"===a.name&&(t(e,a.value),r.close())},onTabChange:(e,t)=>{i.set(t.newTabName),o.throttle(e)},onChange:(e,t)=>{t.name===x&&o.throttle(e)}};e.windowManager.open(c).focus(x)};e.add("charmap",(e=>{(e=>{const t=e.options.register,r=e=>o(e)||a(e);t("charmap",{processor:r}),t("charmap_append",{processor:r})})(e);const r=w(e);return((e,t)=>{e.addCommand("mceShowCharmap",(()=>{A(e,t)}))})(e,r),(e=>{const t=()=>e.execCommand("mceShowCharmap");e.ui.registry.addButton("charmap",{icon:"insert-character",tooltip:"Special character",onAction:t}),e.ui.registry.addMenuItem("charmap",{icon:"insert-character",text:"Special character...",onAction:t})})(e),((e,t)=>{e.ui.registry.addAutocompleter("charmap",{trigger:":",columns:"auto",minChars:2,fetch:(e,r)=>new Promise(((r,a)=>{r(C(t,e))})),onAction:(t,r,a)=>{e.selection.setRng(r),e.insertContent(a),t.hide()}})})(e,r[0]),(e=>({getCharMap:()=>w(e),insertChar:r=>{t(e,r)}}))(e)}))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/code/plugin.min.js b/public/plugins/tinymce/plugins/code/plugin.min.js new file mode 100644 index 000000000..20af25699 --- /dev/null +++ b/public/plugins/tinymce/plugins/code/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("code",(e=>((e=>{e.addCommand("mceCodeEditor",(()=>{(e=>{const o=(e=>e.getContent({source_view:!0}))(e);e.windowManager.open({title:"Source Code",size:"large",body:{type:"panel",items:[{type:"textarea",name:"code"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{code:o},onSubmit:o=>{((e,o)=>{e.focus(),e.undoManager.transact((()=>{e.setContent(o)})),e.selection.setCursorLocation(),e.nodeChanged()})(e,o.getData().code),o.close()}})})(e)}))})(e),(e=>{const o=()=>e.execCommand("mceCodeEditor");e.ui.registry.addButton("code",{icon:"sourcecode",tooltip:"Source code",onAction:o}),e.ui.registry.addMenuItem("code",{icon:"sourcecode",text:"Source code",onAction:o})})(e),{})))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/codesample/plugin.min.js b/public/plugins/tinymce/plugins/codesample/plugin.min.js new file mode 100644 index 000000000..a68373808 --- /dev/null +++ b/public/plugins/tinymce/plugins/codesample/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>!(e=>null==e)(e);class n{constructor(e,t){this.tag=e,this.value=t}static some(e){return new n(!0,e)}static none(){return n.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?n.some(e(this.value)):n.none()}bind(e){return this.tag?e(this.value):n.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:n.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return t(e)?n.some(e):n.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}n.singletonNone=new n(!1);var a=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils");const s="undefined"!=typeof window?window:Function("return this;")(),r=function(e,t,n){const a=window.Prism;window.Prism={manual:!0};var s=function(e){var t=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,n=0,a={},s={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(t){return t instanceof r?new r(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/=d.reach);x+=_.value.length,_=_.next){var F=_.value;if(t.length>e.length)return;if(!(F instanceof r)){var A,S=1;if(y){if(!(A=i(v,x,e,m))||A.index>=e.length)break;var $=A.index,z=A.index+A[0].length,E=x;for(E+=_.value.length;$>=E;)E+=(_=_.next).value.length;if(x=E-=_.value.length,_.value instanceof r)continue;for(var C=_;C!==t.tail&&(Ed.reach&&(d.reach=O);var P=_.prev;if(B&&(P=u(t,P,B),x+=B.length),c(t,P,S),_=u(t,P,new r(g,f?s.tokenize(j,f):j,w,j)),T&&u(t,_,T),S>1){var N={cause:g+","+b,reach:O};o(e,t,n,_.prev,x,N),d&&N.reach>d.reach&&(d.reach=N.reach)}}}}}}function l(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function u(e,t,n){var a=t.next,s={value:n,prev:t,next:a};return t.next=s,a.prev=s,e.length++,s}function c(e,t,n){for(var a=t.next,s=0;s"+r.content+""},!e.document)return e.addEventListener?(s.disableWorkerMessageHandler||e.addEventListener("message",(function(t){var n=JSON.parse(t.data),a=n.language,r=n.code,i=n.immediateClose;e.postMessage(s.highlight(r,s.languages[a],a)),i&&e.close()}),!1),s):s;var d=s.util.currentScript();function g(){s.manual||s.highlightAll()}if(d&&(s.filename=d.src,d.hasAttribute("data-manual")&&(s.manual=!0)),!s.manual){var p=document.readyState;"loading"===p||"interactive"===p&&d&&d.defer?document.addEventListener("DOMContentLoaded",g):window.requestAnimationFrame?window.requestAnimationFrame(g):window.setTimeout(g,16)}return s}("undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{});return s.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,a,s,r){if(n.language===a){var i=n.tokenStack=[];n.code=n.code.replace(s,(function(e){if("function"==typeof r&&!r(e))return e;for(var s,o=i.length;-1!==n.code.indexOf(s=t(a,o));)++o;return i[o]=e,s})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,a){if(n.language===a&&n.tokenStack){n.grammar=e.languages[a];var s=0,r=Object.keys(n.tokenStack);!function i(o){for(var l=0;l=r.length);l++){var u=o[l];if("string"==typeof u||u.content&&"string"==typeof u.content){var c=r[s],d=n.tokenStack[c],g="string"==typeof u?u:u.content,p=t(a,c),b=g.indexOf(p);if(b>-1){++s;var h=g.substring(0,b),f=new e.Token(a,e.tokenize(d,n.grammar),"language-"+a,d),m=g.substring(b+p.length),y=[];h&&y.push.apply(y,i([h])),y.push(f),m&&y.push.apply(y,i([m])),"string"==typeof u?o.splice.apply(o,[l,1].concat(y)):u.content=y}}else u.content&&i(u.content)}return o}(n.tokens)}}}})}(s),s.languages.c=s.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),s.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),s.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},s.languages.c.string],char:s.languages.c.char,comment:s.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:s.languages.c}}}}),s.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete s.languages.c.boolean,function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!)\w+(?:\s*\.\s*\w+)*\b/.source.replace(//g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!)\w+/.source.replace(//g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/(?:\s*:\s*)?|:\s*/.source.replace(//g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(s),function(e){function t(e,t){return e.replace(/<<(\d+)>>/g,(function(e,n){return"(?:"+t[+n]+")"}))}function n(e,n,a){return RegExp(t(e,n),a||"")}function a(e,t){for(var n=0;n>/g,(function(){return"(?:"+e+")"}));return e.replace(/<>/g,"[^\\s\\S]")}var s="bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void",r="class enum interface record struct",i="add alias and ascending async await by descending from(?=\\s*(?:\\w|$)) get global group into init(?=\\s*;) join let nameof not notnull on or orderby partial remove select set unmanaged value when where with(?=\\s*{)",o="abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield";function l(e){return"\\b(?:"+e.trim().replace(/ /g,"|")+")\\b"}var u=l(r),c=RegExp(l(s+" "+r+" "+i+" "+o)),d=l(r+" "+i+" "+o),g=l(s+" "+r+" "+o),p=a(/<(?:[^<>;=+\-*/%&|^]|<>)*>/.source,2),b=a(/\((?:[^()]|<>)*\)/.source,2),h=/@?\b[A-Za-z_]\w*\b/.source,f=t(/<<0>>(?:\s*<<1>>)?/.source,[h,p]),m=t(/(?!<<0>>)<<1>>(?:\s*\.\s*<<1>>)*/.source,[d,f]),y=/\[\s*(?:,\s*)*\]/.source,w=t(/<<0>>(?:\s*(?:\?\s*)?<<1>>)*(?:\s*\?)?/.source,[m,y]),k=t(/[^,()<>[\];=+\-*/%&|^]|<<0>>|<<1>>|<<2>>/.source,[p,b,y]),v=t(/\(<<0>>+(?:,<<0>>+)+\)/.source,[k]),_=t(/(?:<<0>>|<<1>>)(?:\s*(?:\?\s*)?<<2>>)*(?:\s*\?)?/.source,[v,m,y]),x={keyword:c,punctuation:/[<>()?,.:[\]]/},F=/'(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'/.source,A=/"(?:\\.|[^\\"\r\n])*"/.source,S=/@"(?:""|\\[\s\S]|[^\\"])*"(?!")/.source;e.languages.csharp=e.languages.extend("clike",{string:[{pattern:n(/(^|[^$\\])<<0>>/.source,[S]),lookbehind:!0,greedy:!0},{pattern:n(/(^|[^@$\\])<<0>>/.source,[A]),lookbehind:!0,greedy:!0}],"class-name":[{pattern:n(/(\busing\s+static\s+)<<0>>(?=\s*;)/.source,[m]),lookbehind:!0,inside:x},{pattern:n(/(\busing\s+<<0>>\s*=\s*)<<1>>(?=\s*;)/.source,[h,_]),lookbehind:!0,inside:x},{pattern:n(/(\busing\s+)<<0>>(?=\s*=)/.source,[h]),lookbehind:!0},{pattern:n(/(\b<<0>>\s+)<<1>>/.source,[u,f]),lookbehind:!0,inside:x},{pattern:n(/(\bcatch\s*\(\s*)<<0>>/.source,[m]),lookbehind:!0,inside:x},{pattern:n(/(\bwhere\s+)<<0>>/.source,[h]),lookbehind:!0},{pattern:n(/(\b(?:is(?:\s+not)?|as)\s+)<<0>>/.source,[w]),lookbehind:!0,inside:x},{pattern:n(/\b<<0>>(?=\s+(?!<<1>>|with\s*\{)<<2>>(?:\s*[=,;:{)\]]|\s+(?:in|when)\b))/.source,[_,g,h]),inside:x}],keyword:c,number:/(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:[dflmu]|lu|ul)?\b/i,operator:/>>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),e.languages.insertBefore("csharp","number",{range:{pattern:/\.\./,alias:"operator"}}),e.languages.insertBefore("csharp","punctuation",{"named-parameter":{pattern:n(/([(,]\s*)<<0>>(?=\s*:)/.source,[h]),lookbehind:!0,alias:"punctuation"}}),e.languages.insertBefore("csharp","class-name",{namespace:{pattern:n(/(\b(?:namespace|using)\s+)<<0>>(?:\s*\.\s*<<0>>)*(?=\s*[;{])/.source,[h]),lookbehind:!0,inside:{punctuation:/\./}},"type-expression":{pattern:n(/(\b(?:default|sizeof|typeof)\s*\(\s*(?!\s))(?:[^()\s]|\s(?!\s)|<<0>>)*(?=\s*\))/.source,[b]),lookbehind:!0,alias:"class-name",inside:x},"return-type":{pattern:n(/<<0>>(?=\s+(?:<<1>>\s*(?:=>|[({]|\.\s*this\s*\[)|this\s*\[))/.source,[_,m]),inside:x,alias:"class-name"},"constructor-invocation":{pattern:n(/(\bnew\s+)<<0>>(?=\s*[[({])/.source,[_]),lookbehind:!0,inside:x,alias:"class-name"},"generic-method":{pattern:n(/<<0>>\s*<<1>>(?=\s*\()/.source,[h,p]),inside:{function:n(/^<<0>>/.source,[h]),generic:{pattern:RegExp(p),alias:"class-name",inside:x}}},"type-list":{pattern:n(/\b((?:<<0>>\s+<<1>>|record\s+<<1>>\s*<<5>>|where\s+<<2>>)\s*:\s*)(?:<<3>>|<<4>>|<<1>>\s*<<5>>|<<6>>)(?:\s*,\s*(?:<<3>>|<<4>>|<<6>>))*(?=\s*(?:where|[{;]|=>|$))/.source,[u,f,h,_,c.source,b,/\bnew\s*\(\s*\)/.source]),lookbehind:!0,inside:{"record-arguments":{pattern:n(/(^(?!new\s*\()<<0>>\s*)<<1>>/.source,[f,b]),lookbehind:!0,greedy:!0,inside:e.languages.csharp},keyword:c,"class-name":{pattern:RegExp(_),greedy:!0,inside:x},punctuation:/[,()]/}},preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(#)\b(?:define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}});var $=A+"|"+F,z=t(/\/(?![*/])|\/\/[^\r\n]*[\r\n]|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>/.source,[$]),E=a(t(/[^"'/()]|<<0>>|\(<>*\)/.source,[z]),2),C=/\b(?:assembly|event|field|method|module|param|property|return|type)\b/.source,j=t(/<<0>>(?:\s*\(<<1>>*\))?/.source,[m,E]);e.languages.insertBefore("csharp","class-name",{attribute:{pattern:n(/((?:^|[^\s\w>)?])\s*\[\s*)(?:<<0>>\s*:\s*)?<<1>>(?:\s*,\s*<<1>>)*(?=\s*\])/.source,[C,j]),lookbehind:!0,greedy:!0,inside:{target:{pattern:n(/^<<0>>(?=\s*:)/.source,[C]),alias:"keyword"},"attribute-arguments":{pattern:n(/\(<<0>>*\)/.source,[E]),inside:e.languages.csharp},"class-name":{pattern:RegExp(m),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var B=/:[^}\r\n]+/.source,T=a(t(/[^"'/()]|<<0>>|\(<>*\)/.source,[z]),2),O=t(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[T,B]),P=a(t(/[^"'/()]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>|\(<>*\)/.source,[$]),2),N=t(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[P,B]);function R(t,a){return{interpolation:{pattern:n(/((?:^|[^{])(?:\{\{)*)<<0>>/.source,[t]),lookbehind:!0,inside:{"format-string":{pattern:n(/(^\{(?:(?![}:])<<0>>)*)<<1>>(?=\}$)/.source,[a,B]),lookbehind:!0,inside:{punctuation:/^:/}},punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-csharp",inside:e.languages.csharp}}},string:/[\s\S]+/}}e.languages.insertBefore("csharp","string",{"interpolation-string":[{pattern:n(/(^|[^\\])(?:\$@|@\$)"(?:""|\\[\s\S]|\{\{|<<0>>|[^\\{"])*"/.source,[O]),lookbehind:!0,greedy:!0,inside:R(O,T)},{pattern:n(/(^|[^@\\])\$"(?:\\.|\{\{|<<0>>|[^\\"{])*"/.source,[N]),lookbehind:!0,greedy:!0,inside:R(N,P)}],char:{pattern:RegExp(F),greedy:!0}}),e.languages.dotnet=e.languages.cs=e.languages.csharp}(s),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}(s),function(e){var t=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,n=/(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,a={pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[a,{pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z]\w*(?=\s+\w+\s*[;,=()]|\s*(?:\[[\s,]*\]\s*)?::\s*new\b)/.source),lookbehind:!0,inside:a.inside},{pattern:RegExp(/(\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\s+)/.source+n+/[A-Z]\w*\b/.source),lookbehind:!0,inside:a.inside}],keyword:t,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":a,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp(/(\bimport\s+)/.source+n+/(?:[A-Z]\w*|\*)(?=\s*;)/.source),lookbehind:!0,inside:{namespace:a.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp(/(\bimport\s+static\s+)/.source+n+/(?:\w+|\*)(?=\s*;)/.source),lookbehind:!0,alias:"static",inside:{namespace:a.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(//g,(function(){return t.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(s),s.languages.javascript=s.languages.extend("clike",{"class-name":[s.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),s.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,s.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp(/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source+/\//.source+"(?:"+/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source+"|"+/(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source+")"+/(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:s.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:s.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:s.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:s.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:s.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),s.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:s.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),s.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),s.languages.markup&&(s.languages.markup.tag.addInlined("script","javascript"),s.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),s.languages.js=s.languages.javascript,s.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},s.languages.markup.tag.inside["attr-value"].inside.entity=s.languages.markup.entity,s.languages.markup.doctype.inside["internal-subset"].inside=s.languages.markup,s.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(s.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:s.languages[t]},n.cdata=/^$/i;var a={"included-cdata":{pattern://i,inside:n}};a["language-"+t]={pattern:/[\s\S]+/,inside:s.languages[t]};var r={};r[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:a},s.languages.insertBefore("markup","cdata",r)}}),Object.defineProperty(s.languages.markup.tag,"addAttribute",{value:function(e,t){s.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:s.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),s.languages.html=s.languages.markup,s.languages.mathml=s.languages.markup,s.languages.svg=s.languages.markup,s.languages.xml=s.languages.extend("markup",{}),s.languages.ssml=s.languages.xml,s.languages.atom=s.languages.xml,s.languages.rss=s.languages.xml,function(e){var t=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,n=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],a=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,s=/|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,r=/[{}\[\](),:;]/;e.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:t,variable:/\$+(?:\w+\b|(?=\{))/,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:array|bool|boolean|float|int|integer|object|string)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|never|object|self|static|string|void)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:array(?!\s*\()|bool|float|int|iterable|mixed|object|string|void)\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:false|null)\b|\b(?:false|null)(?=\s*\|)/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|never|new|or|parent|print|private|protected|public|readonly|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield|__halt_compiler)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s*)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:n,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:a,operator:s,punctuation:r};var i={pattern:/\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:e.languages.php},o=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:i}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:i}}];e.languages.insertBefore("php","variable",{string:o,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=\]$)/,lookbehind:!0,inside:{comment:t,string:o,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:n,number:a,operator:s,punctuation:r}},delimiter:{pattern:/^#\[|\]$/,alias:"punctuation"}}}}),e.hooks.add("before-tokenize",(function(t){/<\?/.test(t.code)&&e.languages["markup-templating"].buildPlaceholders(t,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/g)})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"php")}))}(s),s.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},s.languages.python["string-interpolation"].inside.interpolation.inside.rest=s.languages.python,s.languages.py=s.languages.python,function(e){e.languages.ruby=e.languages.extend("clike",{comment:{pattern:/#.*|^=begin\s[\s\S]*?^=end/m,greedy:!0},"class-name":{pattern:/(\b(?:class|module)\s+|\bcatch\s+\()[\w.\\]+|\b[A-Z_]\w*(?=\s*\.\s*new\b)/,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:BEGIN|END|alias|and|begin|break|case|class|def|define_method|defined|do|each|else|elsif|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|private|protected|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/,operator:/\.{2,3}|&\.|===||[!=]?~|(?:&&|\|\||<<|>>|\*\*|[+\-*/%<>!^&|=])=?|[?:]/,punctuation:/[(){}[\].,;]/}),e.languages.insertBefore("ruby","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}});var t={pattern:/((?:^|[^\\])(?:\\{2})*)#\{(?:[^{}]|\{[^{}]*\})*\}/,lookbehind:!0,inside:{content:{pattern:/^(#\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:e.languages.ruby},delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"}}};delete e.languages.ruby.function;var n="(?:"+[/([^a-zA-Z0-9\s{(\[<=])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/\((?:[^()\\]|\\[\s\S]|\((?:[^()\\]|\\[\s\S])*\))*\)/.source,/\{(?:[^{}\\]|\\[\s\S]|\{(?:[^{}\\]|\\[\s\S])*\})*\}/.source,/\[(?:[^\[\]\\]|\\[\s\S]|\[(?:[^\[\]\\]|\\[\s\S])*\])*\]/.source,/<(?:[^<>\\]|\\[\s\S]|<(?:[^<>\\]|\\[\s\S])*>)*>/.source].join("|")+")",a=/(?:"(?:\\.|[^"\\\r\n])*"|(?:\b[a-zA-Z_]\w*|[^\s\0-\x7F]+)[?!]?|\$.)/.source;e.languages.insertBefore("ruby","keyword",{"regex-literal":[{pattern:RegExp(/%r/.source+n+/[egimnosux]{0,6}/.source),greedy:!0,inside:{interpolation:t,regex:/[\s\S]+/}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,lookbehind:!0,greedy:!0,inside:{interpolation:t,regex:/[\s\S]+/}}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:[{pattern:RegExp(/(^|[^:]):/.source+a),lookbehind:!0,greedy:!0},{pattern:RegExp(/([\r\n{(,][ \t]*)/.source+a+/(?=:(?!:))/.source),lookbehind:!0,greedy:!0}],"method-definition":{pattern:/(\bdef\s+)\w+(?:\s*\.\s*\w+)?/,lookbehind:!0,inside:{function:/\b\w+$/,keyword:/^self\b/,"class-name":/^\w+/,punctuation:/\./}}}),e.languages.insertBefore("ruby","string",{"string-literal":[{pattern:RegExp(/%[qQiIwWs]?/.source+n),greedy:!0,inside:{interpolation:t,string:/[\s\S]+/}},{pattern:/("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,greedy:!0,inside:{interpolation:t,string:/[\s\S]+/}},{pattern:/<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?[a-z_]\w*|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?/}},interpolation:t,string:/[\s\S]+/}},{pattern:/<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?'[a-z_]\w*'|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?'|'$/}},string:/[\s\S]+/}}],"command-literal":[{pattern:RegExp(/%x/.source+n),greedy:!0,inside:{interpolation:t,command:{pattern:/[\s\S]+/,alias:"string"}}},{pattern:/`(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|[^\\`#\r\n])*`/,greedy:!0,inside:{interpolation:t,command:{pattern:/[\s\S]+/,alias:"string"}}}]}),delete e.languages.ruby.string,e.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Fixnum|Float|Hash|IO|Integer|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|Stat|String|Struct|Symbol|TMS|Thread|ThreadGroup|Time|TrueClass)\b/,constant:/\b[A-Z][A-Z0-9_]*(?:[?!]|\b)/}),e.languages.rb=e.languages.ruby}(s),window.Prism=a,s}(),i=e=>t=>t.options.get(e),o=i("codesample_languages"),l=i("codesample_global_prismjs"),u=e=>s.Prism&&l(e)?s.Prism:r,c=e=>t(e)&&"PRE"===e.nodeName&&-1!==e.className.indexOf("language-"),d=e=>{const t=e.selection?e.selection.getNode():null;return c(t)?n.some(t):n.none()},g=e=>{const t=(e=>o(e)||[{text:"HTML/XML",value:"markup"},{text:"JavaScript",value:"javascript"},{text:"CSS",value:"css"},{text:"PHP",value:"php"},{text:"Ruby",value:"ruby"},{text:"Python",value:"python"},{text:"Java",value:"java"},{text:"C",value:"c"},{text:"C#",value:"csharp"},{text:"C++",value:"cpp"}])(e),s=(r=t,((e,t)=>0""),(e=>e.value));var r;const i=((e,t)=>d(e).fold((()=>t),(e=>{const n=e.className.match(/language-(\w+)/);return n?n[1]:t})))(e,s),l=(e=>d(e).bind((e=>n.from(e.textContent))).getOr(""))(e);e.windowManager.open({title:"Insert/Edit Code Sample",size:"large",body:{type:"panel",items:[{type:"selectbox",name:"language",label:"Language",items:t},{type:"textarea",name:"code",label:"Code view"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{language:i,code:l},onSubmit:t=>{const n=t.getData();((e,t,n)=>{const s=e.dom;e.undoManager.transact((()=>{const r=d(e);return n=a.DOM.encode(n),r.fold((()=>{e.insertContent('
    '+n+"
    ");const a=s.select("#__new")[0];s.setAttrib(a,"id",null),e.selection.select(a)}),(a=>{s.setAttrib(a,"class","language-"+t),a.innerHTML=n,u(e).highlightElement(a),e.selection.select(a)}))}))})(e,n.language,n.code),t.close()}})},p=(b=/^\s+|\s+$/g,e=>e.replace(b,""));var b,h=tinymce.util.Tools.resolve("tinymce.util.Tools");e.add("codesample",(e=>{(e=>{const t=e.options.register;t("codesample_languages",{processor:"object[]"}),t("codesample_global_prismjs",{processor:"boolean",default:!1})})(e),(e=>{e.on("PreProcess",(t=>{const n=e.dom,a=n.select("pre[contenteditable=false]",t.node);h.each(h.grep(a,c),(e=>{const t=e.textContent;let a;for(n.setAttrib(e,"class",p(n.getAttrib(e,"class"))),n.setAttrib(e,"contentEditable",null),n.setAttrib(e,"data-mce-highlighted",null);a=e.firstChild;)e.removeChild(a);n.add(e,"code").textContent=t}))})),e.on("SetContent",(()=>{const t=e.dom,n=h.grep(t.select("pre"),(e=>c(e)&&"true"!==t.getAttrib(e,"data-mce-highlighted")));n.length&&e.undoManager.transact((()=>{h.each(n,(n=>{var a;h.each(t.select("br",n),(n=>{t.replace(e.getDoc().createTextNode("\n"),n)})),n.innerHTML=t.encode(null!==(a=n.textContent)&&void 0!==a?a:""),u(e).highlightElement(n),t.setAttrib(n,"data-mce-highlighted",!0),n.className=p(n.className)}))}))})),e.on("PreInit",(()=>{e.parser.addNodeFilter("pre",(e=>{var t;for(let n=0,a=e.length;n{const t=()=>e.execCommand("codesample");e.ui.registry.addToggleButton("codesample",{icon:"code-sample",tooltip:"Insert/edit code sample",onAction:t,onSetup:t=>{const n=()=>{t.setActive((e=>{const t=e.selection.getStart();return e.dom.is(t,'pre[class*="language-"]')})(e))};return e.on("NodeChange",n),()=>e.off("NodeChange",n)}}),e.ui.registry.addMenuItem("codesample",{text:"Code sample...",icon:"code-sample",onAction:t})})(e),(e=>{e.addCommand("codesample",(()=>{const t=e.selection.getNode();e.selection.isCollapsed()||c(t)?g(e):e.formatter.toggle("code")}))})(e),e.on("dblclick",(t=>{c(t.target)&&g(e)}))}))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/directionality/plugin.min.js b/public/plugins/tinymce/plugins/directionality/plugin.min.js new file mode 100644 index 000000000..4e7f8906f --- /dev/null +++ b/public/plugins/tinymce/plugins/directionality/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=t=>e=>typeof e===t,o=t=>"string"===(t=>{const e=typeof t;return null===t?"null":"object"===e&&Array.isArray(t)?"array":"object"===e&&(o=r=t,(n=String).prototype.isPrototypeOf(o)||(null===(i=r.constructor)||void 0===i?void 0:i.name)===n.name)?"string":e;var o,r,n,i})(t),r=e("boolean"),n=t=>!(t=>null==t)(t),i=e("function"),s=e("number"),l=(!1,()=>false);class a{constructor(t,e){this.tag=t,this.value=e}static some(t){return new a(!0,t)}static none(){return a.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?a.some(t(this.value)):a.none()}bind(t){return this.tag?t(this.value):a.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:a.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return n(t)?a.some(t):a.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}a.singletonNone=new a(!1);const u=(t,e)=>{for(let o=0,r=t.length;o{if(null==t)throw new Error("Node cannot be null or undefined");return{dom:t}},d=c,h=(t,e)=>{const o=t.dom;if(1!==o.nodeType)return!1;{const t=o;if(void 0!==t.matches)return t.matches(e);if(void 0!==t.msMatchesSelector)return t.msMatchesSelector(e);if(void 0!==t.webkitMatchesSelector)return t.webkitMatchesSelector(e);if(void 0!==t.mozMatchesSelector)return t.mozMatchesSelector(e);throw new Error("Browser lacks native selectors")}};"undefined"!=typeof window?window:Function("return this;")();const m=t=>e=>(t=>t.dom.nodeType)(e)===t,g=m(1),f=m(3),v=m(9),p=m(11),y=(t,e)=>{t.dom.removeAttribute(e)},w=i(Element.prototype.attachShadow)&&i(Node.prototype.getRootNode)?t=>d(t.dom.getRootNode()):t=>v(t)?t:d(t.dom.ownerDocument),N=t=>d(t.dom.host),b=t=>{const e=f(t)?t.dom.parentNode:t.dom;if(null==e||null===e.ownerDocument)return!1;const o=e.ownerDocument;return(t=>{const e=w(t);return p(o=e)&&n(o.dom.host)?a.some(e):a.none();var o})(d(e)).fold((()=>o.body.contains(e)),(r=b,i=N,t=>r(i(t))));var r,i},S=t=>"rtl"===((t,e)=>{const o=t.dom,r=window.getComputedStyle(o).getPropertyValue(e);return""!==r||b(t)?r:((t,e)=>(t=>void 0!==t.style&&i(t.style.getPropertyValue))(t)?t.style.getPropertyValue(e):"")(o,e)})(t,"direction")?"rtl":"ltr",A=(t,e)=>((t,o)=>((t,e)=>{const o=[];for(let r=0,n=t.length;r{const o=t.length,r=new Array(o);for(let n=0;nh(t,e))))(t),T=("li",t=>g(t)&&"li"===t.dom.nodeName.toLowerCase());const C=(t,e)=>{const n=t.selection.getSelectedBlocks();n.length>0&&(u(n,(t=>{const n=d(t),c=T(n),m=((t,e)=>{return(e?(o=t,r="ol,ul",((t,e,o)=>{let n=t.dom;const s=i(o)?o:l;for(;n.parentNode;){n=n.parentNode;const t=d(n);if(h(t,r))return a.some(t);if(s(t))break}return a.none()})(o,0,n)):a.some(t)).getOr(t);var o,r,n})(n,c);var f;(f=m,(t=>a.from(t.dom.parentNode).map(d))(f).filter(g)).each((t=>{if(S(t)!==e?((t,e,n)=>{((t,e,n)=>{if(!(o(n)||r(n)||s(n)))throw console.error("Invalid call to Attribute.set. Key ",e,":: Value ",n,":: Element ",t),new Error("Attribute value was not simple");t.setAttribute(e,n+"")})(t.dom,e,n)})(m,"dir",e):S(m)!==e&&y(m,"dir"),c){const t=A(m,"li[dir]");u(t,(t=>y(t,"dir")))}}))})),t.nodeChanged())},D=(t,e)=>o=>{const r=t=>{const r=d(t.element);o.setActive(S(r)===e)};return t.on("NodeChange",r),()=>t.off("NodeChange",r)};t.add("directionality",(t=>{(t=>{t.addCommand("mceDirectionLTR",(()=>{C(t,"ltr")})),t.addCommand("mceDirectionRTL",(()=>{C(t,"rtl")}))})(t),(t=>{t.ui.registry.addToggleButton("ltr",{tooltip:"Left to right",icon:"ltr",onAction:()=>t.execCommand("mceDirectionLTR"),onSetup:D(t,"ltr")}),t.ui.registry.addToggleButton("rtl",{tooltip:"Right to left",icon:"rtl",onAction:()=>t.execCommand("mceDirectionRTL"),onSetup:D(t,"rtl")})})(t)}))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/emoticons/js/emojiimages.js b/public/plugins/tinymce/plugins/emoticons/js/emojiimages.js new file mode 100644 index 000000000..6fcec717a --- /dev/null +++ b/public/plugins/tinymce/plugins/emoticons/js/emojiimages.js @@ -0,0 +1 @@ +window.tinymce.Resource.add("tinymce.plugins.emoticons",{100:{keywords:["score","perfect","numbers","century","exam","quiz","test","pass","hundred"],char:'💯',fitzpatrick_scale:false,category:"symbols"},1234:{keywords:["numbers","blue-square"],char:'🔢',fitzpatrick_scale:false,category:"symbols"},grinning:{keywords:["face","smile","happy","joy",":D","grin"],char:'😀',fitzpatrick_scale:false,category:"people"},grimacing:{keywords:["face","grimace","teeth"],char:'😬',fitzpatrick_scale:false,category:"people"},grin:{keywords:["face","happy","smile","joy","kawaii"],char:'😁',fitzpatrick_scale:false,category:"people"},joy:{keywords:["face","cry","tears","weep","happy","happytears","haha"],char:'😂',fitzpatrick_scale:false,category:"people"},rofl:{keywords:["face","rolling","floor","laughing","lol","haha"],char:'🤣',fitzpatrick_scale:false,category:"people"},partying:{keywords:["face","celebration","woohoo"],char:'🥳',fitzpatrick_scale:false,category:"people"},smiley:{keywords:["face","happy","joy","haha",":D",":)","smile","funny"],char:'😃',fitzpatrick_scale:false,category:"people"},smile:{keywords:["face","happy","joy","funny","haha","laugh","like",":D",":)"],char:'😄',fitzpatrick_scale:false,category:"people"},sweat_smile:{keywords:["face","hot","happy","laugh","sweat","smile","relief"],char:'😅',fitzpatrick_scale:false,category:"people"},laughing:{keywords:["happy","joy","lol","satisfied","haha","face","glad","XD","laugh"],char:'😆',fitzpatrick_scale:false,category:"people"},innocent:{keywords:["face","angel","heaven","halo"],char:'😇',fitzpatrick_scale:false,category:"people"},wink:{keywords:["face","happy","mischievous","secret",";)","smile","eye"],char:'😉',fitzpatrick_scale:false,category:"people"},blush:{keywords:["face","smile","happy","flushed","crush","embarrassed","shy","joy"],char:'😊',fitzpatrick_scale:false,category:"people"},slightly_smiling_face:{keywords:["face","smile"],char:'🙂',fitzpatrick_scale:false,category:"people"},upside_down_face:{keywords:["face","flipped","silly","smile"],char:'🙃',fitzpatrick_scale:false,category:"people"},relaxed:{keywords:["face","blush","massage","happiness"],char:'☺️',fitzpatrick_scale:false,category:"people"},yum:{keywords:["happy","joy","tongue","smile","face","silly","yummy","nom","delicious","savouring"],char:'😋',fitzpatrick_scale:false,category:"people"},relieved:{keywords:["face","relaxed","phew","massage","happiness"],char:'😌',fitzpatrick_scale:false,category:"people"},heart_eyes:{keywords:["face","love","like","affection","valentines","infatuation","crush","heart"],char:'😍',fitzpatrick_scale:false,category:"people"},smiling_face_with_three_hearts:{keywords:["face","love","like","affection","valentines","infatuation","crush","hearts","adore"],char:'🥰',fitzpatrick_scale:false,category:"people"},kissing_heart:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:'😘',fitzpatrick_scale:false,category:"people"},kissing:{keywords:["love","like","face","3","valentines","infatuation","kiss"],char:'😗',fitzpatrick_scale:false,category:"people"},kissing_smiling_eyes:{keywords:["face","affection","valentines","infatuation","kiss"],char:'😙',fitzpatrick_scale:false,category:"people"},kissing_closed_eyes:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:'😚',fitzpatrick_scale:false,category:"people"},stuck_out_tongue_winking_eye:{keywords:["face","prank","childish","playful","mischievous","smile","wink","tongue"],char:'😜',fitzpatrick_scale:false,category:"people"},zany:{keywords:["face","goofy","crazy"],char:'🤪',fitzpatrick_scale:false,category:"people"},raised_eyebrow:{keywords:["face","distrust","scepticism","disapproval","disbelief","surprise"],char:'🤨',fitzpatrick_scale:false,category:"people"},monocle:{keywords:["face","stuffy","wealthy"],char:'🧐',fitzpatrick_scale:false,category:"people"},stuck_out_tongue_closed_eyes:{keywords:["face","prank","playful","mischievous","smile","tongue"],char:'😝',fitzpatrick_scale:false,category:"people"},stuck_out_tongue:{keywords:["face","prank","childish","playful","mischievous","smile","tongue"],char:'😛',fitzpatrick_scale:false,category:"people"},money_mouth_face:{keywords:["face","rich","dollar","money"],char:'🤑',fitzpatrick_scale:false,category:"people"},nerd_face:{keywords:["face","nerdy","geek","dork"],char:'🤓',fitzpatrick_scale:false,category:"people"},sunglasses:{keywords:["face","cool","smile","summer","beach","sunglass"],char:'😎',fitzpatrick_scale:false,category:"people"},star_struck:{keywords:["face","smile","starry","eyes","grinning"],char:'🤩',fitzpatrick_scale:false,category:"people"},clown_face:{keywords:["face"],char:'🤡',fitzpatrick_scale:false,category:"people"},cowboy_hat_face:{keywords:["face","cowgirl","hat"],char:'🤠',fitzpatrick_scale:false,category:"people"},hugs:{keywords:["face","smile","hug"],char:'🤗',fitzpatrick_scale:false,category:"people"},smirk:{keywords:["face","smile","mean","prank","smug","sarcasm"],char:'😏',fitzpatrick_scale:false,category:"people"},no_mouth:{keywords:["face","hellokitty"],char:'😶',fitzpatrick_scale:false,category:"people"},neutral_face:{keywords:["indifference","meh",":|","neutral"],char:'😐',fitzpatrick_scale:false,category:"people"},expressionless:{keywords:["face","indifferent","-_-","meh","deadpan"],char:'😑',fitzpatrick_scale:false,category:"people"},unamused:{keywords:["indifference","bored","straight face","serious","sarcasm","unimpressed","skeptical","dubious","side_eye"],char:'😒',fitzpatrick_scale:false,category:"people"},roll_eyes:{keywords:["face","eyeroll","frustrated"],char:'🙄',fitzpatrick_scale:false,category:"people"},thinking:{keywords:["face","hmmm","think","consider"],char:'🤔',fitzpatrick_scale:false,category:"people"},lying_face:{keywords:["face","lie","pinocchio"],char:'🤥',fitzpatrick_scale:false,category:"people"},hand_over_mouth:{keywords:["face","whoops","shock","surprise"],char:'🤭',fitzpatrick_scale:false,category:"people"},shushing:{keywords:["face","quiet","shhh"],char:'🤫',fitzpatrick_scale:false,category:"people"},symbols_over_mouth:{keywords:["face","swearing","cursing","cussing","profanity","expletive"],char:'🤬',fitzpatrick_scale:false,category:"people"},exploding_head:{keywords:["face","shocked","mind","blown"],char:'🤯',fitzpatrick_scale:false,category:"people"},flushed:{keywords:["face","blush","shy","flattered"],char:'😳',fitzpatrick_scale:false,category:"people"},disappointed:{keywords:["face","sad","upset","depressed",":("],char:'😞',fitzpatrick_scale:false,category:"people"},worried:{keywords:["face","concern","nervous",":("],char:'😟',fitzpatrick_scale:false,category:"people"},angry:{keywords:["mad","face","annoyed","frustrated"],char:'😠',fitzpatrick_scale:false,category:"people"},rage:{keywords:["angry","mad","hate","despise"],char:'😡',fitzpatrick_scale:false,category:"people"},pensive:{keywords:["face","sad","depressed","upset"],char:'😔',fitzpatrick_scale:false,category:"people"},confused:{keywords:["face","indifference","huh","weird","hmmm",":/"],char:'😕',fitzpatrick_scale:false,category:"people"},slightly_frowning_face:{keywords:["face","frowning","disappointed","sad","upset"],char:'🙁',fitzpatrick_scale:false,category:"people"},frowning_face:{keywords:["face","sad","upset","frown"],char:'☹',fitzpatrick_scale:false,category:"people"},persevere:{keywords:["face","sick","no","upset","oops"],char:'😣',fitzpatrick_scale:false,category:"people"},confounded:{keywords:["face","confused","sick","unwell","oops",":S"],char:'😖',fitzpatrick_scale:false,category:"people"},tired_face:{keywords:["sick","whine","upset","frustrated"],char:'😫',fitzpatrick_scale:false,category:"people"},weary:{keywords:["face","tired","sleepy","sad","frustrated","upset"],char:'😩',fitzpatrick_scale:false,category:"people"},pleading:{keywords:["face","begging","mercy"],char:'🥺',fitzpatrick_scale:false,category:"people"},triumph:{keywords:["face","gas","phew","proud","pride"],char:'😤',fitzpatrick_scale:false,category:"people"},open_mouth:{keywords:["face","surprise","impressed","wow","whoa",":O"],char:'😮',fitzpatrick_scale:false,category:"people"},scream:{keywords:["face","munch","scared","omg"],char:'😱',fitzpatrick_scale:false,category:"people"},fearful:{keywords:["face","scared","terrified","nervous","oops","huh"],char:'😨',fitzpatrick_scale:false,category:"people"},cold_sweat:{keywords:["face","nervous","sweat"],char:'😰',fitzpatrick_scale:false,category:"people"},hushed:{keywords:["face","woo","shh"],char:'😯',fitzpatrick_scale:false,category:"people"},frowning:{keywords:["face","aw","what"],char:'😦',fitzpatrick_scale:false,category:"people"},anguished:{keywords:["face","stunned","nervous"],char:'😧',fitzpatrick_scale:false,category:"people"},cry:{keywords:["face","tears","sad","depressed","upset",":'("],char:'😢',fitzpatrick_scale:false,category:"people"},disappointed_relieved:{keywords:["face","phew","sweat","nervous"],char:'😥',fitzpatrick_scale:false,category:"people"},drooling_face:{keywords:["face"],char:'🤤',fitzpatrick_scale:false,category:"people"},sleepy:{keywords:["face","tired","rest","nap"],char:'😪',fitzpatrick_scale:false,category:"people"},sweat:{keywords:["face","hot","sad","tired","exercise"],char:'😓',fitzpatrick_scale:false,category:"people"},hot:{keywords:["face","feverish","heat","red","sweating"],char:'🥵',fitzpatrick_scale:false,category:"people"},cold:{keywords:["face","blue","freezing","frozen","frostbite","icicles"],char:'🥶',fitzpatrick_scale:false,category:"people"},sob:{keywords:["face","cry","tears","sad","upset","depressed"],char:'😭',fitzpatrick_scale:false,category:"people"},dizzy_face:{keywords:["spent","unconscious","xox","dizzy"],char:'😵',fitzpatrick_scale:false,category:"people"},astonished:{keywords:["face","xox","surprised","poisoned"],char:'😲',fitzpatrick_scale:false,category:"people"},zipper_mouth_face:{keywords:["face","sealed","zipper","secret"],char:'🤐',fitzpatrick_scale:false,category:"people"},nauseated_face:{keywords:["face","vomit","gross","green","sick","throw up","ill"],char:'🤢',fitzpatrick_scale:false,category:"people"},sneezing_face:{keywords:["face","gesundheit","sneeze","sick","allergy"],char:'🤧',fitzpatrick_scale:false,category:"people"},vomiting:{keywords:["face","sick"],char:'🤮',fitzpatrick_scale:false,category:"people"},mask:{keywords:["face","sick","ill","disease"],char:'😷',fitzpatrick_scale:false,category:"people"},face_with_thermometer:{keywords:["sick","temperature","thermometer","cold","fever"],char:'🤒',fitzpatrick_scale:false,category:"people"},face_with_head_bandage:{keywords:["injured","clumsy","bandage","hurt"],char:'🤕',fitzpatrick_scale:false,category:"people"},woozy:{keywords:["face","dizzy","intoxicated","tipsy","wavy"],char:'🥴',fitzpatrick_scale:false,category:"people"},sleeping:{keywords:["face","tired","sleepy","night","zzz"],char:'😴',fitzpatrick_scale:false,category:"people"},zzz:{keywords:["sleepy","tired","dream"],char:'💤',fitzpatrick_scale:false,category:"people"},poop:{keywords:["hankey","shitface","fail","turd","shit"],char:'💩',fitzpatrick_scale:false,category:"people"},smiling_imp:{keywords:["devil","horns"],char:'😈',fitzpatrick_scale:false,category:"people"},imp:{keywords:["devil","angry","horns"],char:'👿',fitzpatrick_scale:false,category:"people"},japanese_ogre:{keywords:["monster","red","mask","halloween","scary","creepy","devil","demon","japanese","ogre"],char:'👹',fitzpatrick_scale:false,category:"people"},japanese_goblin:{keywords:["red","evil","mask","monster","scary","creepy","japanese","goblin"],char:'👺',fitzpatrick_scale:false,category:"people"},skull:{keywords:["dead","skeleton","creepy","death"],char:'💀',fitzpatrick_scale:false,category:"people"},ghost:{keywords:["halloween","spooky","scary"],char:'👻',fitzpatrick_scale:false,category:"people"},alien:{keywords:["UFO","paul","weird","outer_space"],char:'👽',fitzpatrick_scale:false,category:"people"},robot:{keywords:["computer","machine","bot"],char:'🤖',fitzpatrick_scale:false,category:"people"},smiley_cat:{keywords:["animal","cats","happy","smile"],char:'😺',fitzpatrick_scale:false,category:"people"},smile_cat:{keywords:["animal","cats","smile"],char:'😸',fitzpatrick_scale:false,category:"people"},joy_cat:{keywords:["animal","cats","haha","happy","tears"],char:'😹',fitzpatrick_scale:false,category:"people"},heart_eyes_cat:{keywords:["animal","love","like","affection","cats","valentines","heart"],char:'😻',fitzpatrick_scale:false,category:"people"},smirk_cat:{keywords:["animal","cats","smirk"],char:'😼',fitzpatrick_scale:false,category:"people"},kissing_cat:{keywords:["animal","cats","kiss"],char:'😽',fitzpatrick_scale:false,category:"people"},scream_cat:{keywords:["animal","cats","munch","scared","scream"],char:'🙀',fitzpatrick_scale:false,category:"people"},crying_cat_face:{keywords:["animal","tears","weep","sad","cats","upset","cry"],char:'😿',fitzpatrick_scale:false,category:"people"},pouting_cat:{keywords:["animal","cats"],char:'😾',fitzpatrick_scale:false,category:"people"},palms_up:{keywords:["hands","gesture","cupped","prayer"],char:'🤲',fitzpatrick_scale:true,category:"people"},raised_hands:{keywords:["gesture","hooray","yea","celebration","hands"],char:'🙌',fitzpatrick_scale:true,category:"people"},clap:{keywords:["hands","praise","applause","congrats","yay"],char:'👏',fitzpatrick_scale:true,category:"people"},wave:{keywords:["hands","gesture","goodbye","solong","farewell","hello","hi","palm"],char:'👋',fitzpatrick_scale:true,category:"people"},call_me_hand:{keywords:["hands","gesture"],char:'🤙',fitzpatrick_scale:true,category:"people"},"+1":{keywords:["thumbsup","yes","awesome","good","agree","accept","cool","hand","like"],char:'👍',fitzpatrick_scale:true,category:"people"},"-1":{keywords:["thumbsdown","no","dislike","hand"],char:'👎',fitzpatrick_scale:true,category:"people"},facepunch:{keywords:["angry","violence","fist","hit","attack","hand"],char:'👊',fitzpatrick_scale:true,category:"people"},fist:{keywords:["fingers","hand","grasp"],char:'✊',fitzpatrick_scale:true,category:"people"},fist_left:{keywords:["hand","fistbump"],char:'🤛',fitzpatrick_scale:true,category:"people"},fist_right:{keywords:["hand","fistbump"],char:'🤜',fitzpatrick_scale:true,category:"people"},v:{keywords:["fingers","ohyeah","hand","peace","victory","two"],char:'✌',fitzpatrick_scale:true,category:"people"},ok_hand:{keywords:["fingers","limbs","perfect","ok","okay"],char:'👌',fitzpatrick_scale:true,category:"people"},raised_hand:{keywords:["fingers","stop","highfive","palm","ban"],char:'✋',fitzpatrick_scale:true,category:"people"},raised_back_of_hand:{keywords:["fingers","raised","backhand"],char:'🤚',fitzpatrick_scale:true,category:"people"},open_hands:{keywords:["fingers","butterfly","hands","open"],char:'👐',fitzpatrick_scale:true,category:"people"},muscle:{keywords:["arm","flex","hand","summer","strong","biceps"],char:'💪',fitzpatrick_scale:true,category:"people"},pray:{keywords:["please","hope","wish","namaste","highfive"],char:'🙏',fitzpatrick_scale:true,category:"people"},foot:{keywords:["kick","stomp"],char:'🦶',fitzpatrick_scale:true,category:"people"},leg:{keywords:["kick","limb"],char:'🦵',fitzpatrick_scale:true,category:"people"},handshake:{keywords:["agreement","shake"],char:'🤝',fitzpatrick_scale:false,category:"people"},point_up:{keywords:["hand","fingers","direction","up"],char:'☝',fitzpatrick_scale:true,category:"people"},point_up_2:{keywords:["fingers","hand","direction","up"],char:'👆',fitzpatrick_scale:true,category:"people"},point_down:{keywords:["fingers","hand","direction","down"],char:'👇',fitzpatrick_scale:true,category:"people"},point_left:{keywords:["direction","fingers","hand","left"],char:'👈',fitzpatrick_scale:true,category:"people"},point_right:{keywords:["fingers","hand","direction","right"],char:'👉',fitzpatrick_scale:true,category:"people"},fu:{keywords:["hand","fingers","rude","middle","flipping"],char:'🖕',fitzpatrick_scale:true,category:"people"},raised_hand_with_fingers_splayed:{keywords:["hand","fingers","palm"],char:'🖐',fitzpatrick_scale:true,category:"people"},love_you:{keywords:["hand","fingers","gesture"],char:'🤟',fitzpatrick_scale:true,category:"people"},metal:{keywords:["hand","fingers","evil_eye","sign_of_horns","rock_on"],char:'🤘',fitzpatrick_scale:true,category:"people"},crossed_fingers:{keywords:["good","lucky"],char:'🤞',fitzpatrick_scale:true,category:"people"},vulcan_salute:{keywords:["hand","fingers","spock","star trek"],char:'🖖',fitzpatrick_scale:true,category:"people"},writing_hand:{keywords:["lower_left_ballpoint_pen","stationery","write","compose"],char:'✍',fitzpatrick_scale:true,category:"people"},selfie:{keywords:["camera","phone"],char:'🤳',fitzpatrick_scale:true,category:"people"},nail_care:{keywords:["beauty","manicure","finger","fashion","nail"],char:'💅',fitzpatrick_scale:true,category:"people"},lips:{keywords:["mouth","kiss"],char:'👄',fitzpatrick_scale:false,category:"people"},tooth:{keywords:["teeth","dentist"],char:'🦷',fitzpatrick_scale:false,category:"people"},tongue:{keywords:["mouth","playful"],char:'👅',fitzpatrick_scale:false,category:"people"},ear:{keywords:["face","hear","sound","listen"],char:'👂',fitzpatrick_scale:true,category:"people"},nose:{keywords:["smell","sniff"],char:'👃',fitzpatrick_scale:true,category:"people"},eye:{keywords:["face","look","see","watch","stare"],char:'👁',fitzpatrick_scale:false,category:"people"},eyes:{keywords:["look","watch","stalk","peek","see"],char:'👀',fitzpatrick_scale:false,category:"people"},brain:{keywords:["smart","intelligent"],char:'🧠',fitzpatrick_scale:false,category:"people"},bust_in_silhouette:{keywords:["user","person","human"],char:'👤',fitzpatrick_scale:false,category:"people"},busts_in_silhouette:{keywords:["user","person","human","group","team"],char:'👥',fitzpatrick_scale:false,category:"people"},speaking_head:{keywords:["user","person","human","sing","say","talk"],char:'🗣',fitzpatrick_scale:false,category:"people"},baby:{keywords:["child","boy","girl","toddler"],char:'👶',fitzpatrick_scale:true,category:"people"},child:{keywords:["gender-neutral","young"],char:'🧒',fitzpatrick_scale:true,category:"people"},boy:{keywords:["man","male","guy","teenager"],char:'👦',fitzpatrick_scale:true,category:"people"},girl:{keywords:["female","woman","teenager"],char:'👧',fitzpatrick_scale:true,category:"people"},adult:{keywords:["gender-neutral","person"],char:'🧑',fitzpatrick_scale:true,category:"people"},man:{keywords:["mustache","father","dad","guy","classy","sir","moustache"],char:'👨',fitzpatrick_scale:true,category:"people"},woman:{keywords:["female","girls","lady"],char:'👩',fitzpatrick_scale:true,category:"people"},blonde_woman:{keywords:["woman","female","girl","blonde","person"],char:'👱‍♀️',fitzpatrick_scale:true,category:"people"},blonde_man:{keywords:["man","male","boy","blonde","guy","person"],char:'👱',fitzpatrick_scale:true,category:"people"},bearded_person:{keywords:["person","bewhiskered"],char:'🧔',fitzpatrick_scale:true,category:"people"},older_adult:{keywords:["human","elder","senior","gender-neutral"],char:'🧓',fitzpatrick_scale:true,category:"people"},older_man:{keywords:["human","male","men","old","elder","senior"],char:'👴',fitzpatrick_scale:true,category:"people"},older_woman:{keywords:["human","female","women","lady","old","elder","senior"],char:'👵',fitzpatrick_scale:true,category:"people"},man_with_gua_pi_mao:{keywords:["male","boy","chinese"],char:'👲',fitzpatrick_scale:true,category:"people"},woman_with_headscarf:{keywords:["female","hijab","mantilla","tichel"],char:'🧕',fitzpatrick_scale:true,category:"people"},woman_with_turban:{keywords:["female","indian","hinduism","arabs","woman"],char:'👳‍♀️',fitzpatrick_scale:true,category:"people"},man_with_turban:{keywords:["male","indian","hinduism","arabs"],char:'👳',fitzpatrick_scale:true,category:"people"},policewoman:{keywords:["woman","police","law","legal","enforcement","arrest","911","female"],char:'👮‍♀️',fitzpatrick_scale:true,category:"people"},policeman:{keywords:["man","police","law","legal","enforcement","arrest","911"],char:'👮',fitzpatrick_scale:true,category:"people"},construction_worker_woman:{keywords:["female","human","wip","build","construction","worker","labor","woman"],char:'👷‍♀️',fitzpatrick_scale:true,category:"people"},construction_worker_man:{keywords:["male","human","wip","guy","build","construction","worker","labor"],char:'👷',fitzpatrick_scale:true,category:"people"},guardswoman:{keywords:["uk","gb","british","female","royal","woman"],char:'💂‍♀️',fitzpatrick_scale:true,category:"people"},guardsman:{keywords:["uk","gb","british","male","guy","royal"],char:'💂',fitzpatrick_scale:true,category:"people"},female_detective:{keywords:["human","spy","detective","female","woman"],char:'🕵️‍♀️',fitzpatrick_scale:true,category:"people"},male_detective:{keywords:["human","spy","detective"],char:'🕵',fitzpatrick_scale:true,category:"people"},woman_health_worker:{keywords:["doctor","nurse","therapist","healthcare","woman","human"],char:'👩‍⚕️',fitzpatrick_scale:true,category:"people"},man_health_worker:{keywords:["doctor","nurse","therapist","healthcare","man","human"],char:'👨‍⚕️',fitzpatrick_scale:true,category:"people"},woman_farmer:{keywords:["rancher","gardener","woman","human"],char:'👩‍🌾',fitzpatrick_scale:true,category:"people"},man_farmer:{keywords:["rancher","gardener","man","human"],char:'👨‍🌾',fitzpatrick_scale:true,category:"people"},woman_cook:{keywords:["chef","woman","human"],char:'👩‍🍳',fitzpatrick_scale:true,category:"people"},man_cook:{keywords:["chef","man","human"],char:'👨‍🍳',fitzpatrick_scale:true,category:"people"},woman_student:{keywords:["graduate","woman","human"],char:'👩‍🎓',fitzpatrick_scale:true,category:"people"},man_student:{keywords:["graduate","man","human"],char:'👨‍🎓',fitzpatrick_scale:true,category:"people"},woman_singer:{keywords:["rockstar","entertainer","woman","human"],char:'👩‍🎤',fitzpatrick_scale:true,category:"people"},man_singer:{keywords:["rockstar","entertainer","man","human"],char:'👨‍🎤',fitzpatrick_scale:true,category:"people"},woman_teacher:{keywords:["instructor","professor","woman","human"],char:'👩‍🏫',fitzpatrick_scale:true,category:"people"},man_teacher:{keywords:["instructor","professor","man","human"],char:'👨‍🏫',fitzpatrick_scale:true,category:"people"},woman_factory_worker:{keywords:["assembly","industrial","woman","human"],char:'👩‍🏭',fitzpatrick_scale:true,category:"people"},man_factory_worker:{keywords:["assembly","industrial","man","human"],char:'👨‍🏭',fitzpatrick_scale:true,category:"people"},woman_technologist:{keywords:["coder","developer","engineer","programmer","software","woman","human","laptop","computer"],char:'👩‍💻',fitzpatrick_scale:true,category:"people"},man_technologist:{keywords:["coder","developer","engineer","programmer","software","man","human","laptop","computer"],char:'👨‍💻',fitzpatrick_scale:true,category:"people"},woman_office_worker:{keywords:["business","manager","woman","human"],char:'👩‍💼',fitzpatrick_scale:true,category:"people"},man_office_worker:{keywords:["business","manager","man","human"],char:'👨‍💼',fitzpatrick_scale:true,category:"people"},woman_mechanic:{keywords:["plumber","woman","human","wrench"],char:'👩‍🔧',fitzpatrick_scale:true,category:"people"},man_mechanic:{keywords:["plumber","man","human","wrench"],char:'👨‍🔧',fitzpatrick_scale:true,category:"people"},woman_scientist:{keywords:["biologist","chemist","engineer","physicist","woman","human"],char:'👩‍🔬',fitzpatrick_scale:true,category:"people"},man_scientist:{keywords:["biologist","chemist","engineer","physicist","man","human"],char:'👨‍🔬',fitzpatrick_scale:true,category:"people"},woman_artist:{keywords:["painter","woman","human"],char:'👩‍🎨',fitzpatrick_scale:true,category:"people"},man_artist:{keywords:["painter","man","human"],char:'👨‍🎨',fitzpatrick_scale:true,category:"people"},woman_firefighter:{keywords:["fireman","woman","human"],char:'👩‍🚒',fitzpatrick_scale:true,category:"people"},man_firefighter:{keywords:["fireman","man","human"],char:'👨‍🚒',fitzpatrick_scale:true,category:"people"},woman_pilot:{keywords:["aviator","plane","woman","human"],char:'👩‍✈️',fitzpatrick_scale:true,category:"people"},man_pilot:{keywords:["aviator","plane","man","human"],char:'👨‍✈️',fitzpatrick_scale:true,category:"people"},woman_astronaut:{keywords:["space","rocket","woman","human"],char:'👩‍🚀',fitzpatrick_scale:true,category:"people"},man_astronaut:{keywords:["space","rocket","man","human"],char:'👨‍🚀',fitzpatrick_scale:true,category:"people"},woman_judge:{keywords:["justice","court","woman","human"],char:'👩‍⚖️',fitzpatrick_scale:true,category:"people"},man_judge:{keywords:["justice","court","man","human"],char:'👨‍⚖️',fitzpatrick_scale:true,category:"people"},woman_superhero:{keywords:["woman","female","good","heroine","superpowers"],char:'🦸‍♀️',fitzpatrick_scale:true,category:"people"},man_superhero:{keywords:["man","male","good","hero","superpowers"],char:'🦸‍♂️',fitzpatrick_scale:true,category:"people"},woman_supervillain:{keywords:["woman","female","evil","bad","criminal","heroine","superpowers"],char:'🦹‍♀️',fitzpatrick_scale:true,category:"people"},man_supervillain:{keywords:["man","male","evil","bad","criminal","hero","superpowers"],char:'🦹‍♂️',fitzpatrick_scale:true,category:"people"},mrs_claus:{keywords:["woman","female","xmas","mother christmas"],char:'🤶',fitzpatrick_scale:true,category:"people"},santa:{keywords:["festival","man","male","xmas","father christmas"],char:'🎅',fitzpatrick_scale:true,category:"people"},sorceress:{keywords:["woman","female","mage","witch"],char:'🧙‍♀️',fitzpatrick_scale:true,category:"people"},wizard:{keywords:["man","male","mage","sorcerer"],char:'🧙‍♂️',fitzpatrick_scale:true,category:"people"},woman_elf:{keywords:["woman","female"],char:'🧝‍♀️',fitzpatrick_scale:true,category:"people"},man_elf:{keywords:["man","male"],char:'🧝‍♂️',fitzpatrick_scale:true,category:"people"},woman_vampire:{keywords:["woman","female"],char:'🧛‍♀️',fitzpatrick_scale:true,category:"people"},man_vampire:{keywords:["man","male","dracula"],char:'🧛‍♂️',fitzpatrick_scale:true,category:"people"},woman_zombie:{keywords:["woman","female","undead","walking dead"],char:'🧟‍♀️',fitzpatrick_scale:false,category:"people"},man_zombie:{keywords:["man","male","dracula","undead","walking dead"],char:'🧟‍♂️',fitzpatrick_scale:false,category:"people"},woman_genie:{keywords:["woman","female"],char:'🧞‍♀️',fitzpatrick_scale:false,category:"people"},man_genie:{keywords:["man","male"],char:'🧞‍♂️',fitzpatrick_scale:false,category:"people"},mermaid:{keywords:["woman","female","merwoman","ariel"],char:'🧜‍♀️',fitzpatrick_scale:true,category:"people"},merman:{keywords:["man","male","triton"],char:'🧜‍♂️',fitzpatrick_scale:true,category:"people"},woman_fairy:{keywords:["woman","female"],char:'🧚‍♀️',fitzpatrick_scale:true,category:"people"},man_fairy:{keywords:["man","male"],char:'🧚‍♂️',fitzpatrick_scale:true,category:"people"},angel:{keywords:["heaven","wings","halo"],char:'👼',fitzpatrick_scale:true,category:"people"},pregnant_woman:{keywords:["baby"],char:'🤰',fitzpatrick_scale:true,category:"people"},breastfeeding:{keywords:["nursing","baby"],char:'🤱',fitzpatrick_scale:true,category:"people"},princess:{keywords:["girl","woman","female","blond","crown","royal","queen"],char:'👸',fitzpatrick_scale:true,category:"people"},prince:{keywords:["boy","man","male","crown","royal","king"],char:'🤴',fitzpatrick_scale:true,category:"people"},bride_with_veil:{keywords:["couple","marriage","wedding","woman","bride"],char:'👰',fitzpatrick_scale:true,category:"people"},man_in_tuxedo:{keywords:["couple","marriage","wedding","groom"],char:'🤵',fitzpatrick_scale:true,category:"people"},running_woman:{keywords:["woman","walking","exercise","race","running","female"],char:'🏃‍♀️',fitzpatrick_scale:true,category:"people"},running_man:{keywords:["man","walking","exercise","race","running"],char:'🏃',fitzpatrick_scale:true,category:"people"},walking_woman:{keywords:["human","feet","steps","woman","female"],char:'🚶‍♀️',fitzpatrick_scale:true,category:"people"},walking_man:{keywords:["human","feet","steps"],char:'🚶',fitzpatrick_scale:true,category:"people"},dancer:{keywords:["female","girl","woman","fun"],char:'💃',fitzpatrick_scale:true,category:"people"},man_dancing:{keywords:["male","boy","fun","dancer"],char:'🕺',fitzpatrick_scale:true,category:"people"},dancing_women:{keywords:["female","bunny","women","girls"],char:'👯',fitzpatrick_scale:false,category:"people"},dancing_men:{keywords:["male","bunny","men","boys"],char:'👯‍♂️',fitzpatrick_scale:false,category:"people"},couple:{keywords:["pair","people","human","love","date","dating","like","affection","valentines","marriage"],char:'👫',fitzpatrick_scale:false,category:"people"},two_men_holding_hands:{keywords:["pair","couple","love","like","bromance","friendship","people","human"],char:'👬',fitzpatrick_scale:false,category:"people"},two_women_holding_hands:{keywords:["pair","friendship","couple","love","like","female","people","human"],char:'👭',fitzpatrick_scale:false,category:"people"},bowing_woman:{keywords:["woman","female","girl"],char:'🙇‍♀️',fitzpatrick_scale:true,category:"people"},bowing_man:{keywords:["man","male","boy"],char:'🙇',fitzpatrick_scale:true,category:"people"},man_facepalming:{keywords:["man","male","boy","disbelief"],char:'🤦‍♂️',fitzpatrick_scale:true,category:"people"},woman_facepalming:{keywords:["woman","female","girl","disbelief"],char:'🤦‍♀️',fitzpatrick_scale:true,category:"people"},woman_shrugging:{keywords:["woman","female","girl","confused","indifferent","doubt"],char:'🤷',fitzpatrick_scale:true,category:"people"},man_shrugging:{keywords:["man","male","boy","confused","indifferent","doubt"],char:'🤷‍♂️',fitzpatrick_scale:true,category:"people"},tipping_hand_woman:{keywords:["female","girl","woman","human","information"],char:'💁',fitzpatrick_scale:true,category:"people"},tipping_hand_man:{keywords:["male","boy","man","human","information"],char:'💁‍♂️',fitzpatrick_scale:true,category:"people"},no_good_woman:{keywords:["female","girl","woman","nope"],char:'🙅',fitzpatrick_scale:true,category:"people"},no_good_man:{keywords:["male","boy","man","nope"],char:'🙅‍♂️',fitzpatrick_scale:true,category:"people"},ok_woman:{keywords:["women","girl","female","pink","human","woman"],char:'🙆',fitzpatrick_scale:true,category:"people"},ok_man:{keywords:["men","boy","male","blue","human","man"],char:'🙆‍♂️',fitzpatrick_scale:true,category:"people"},raising_hand_woman:{keywords:["female","girl","woman"],char:'🙋',fitzpatrick_scale:true,category:"people"},raising_hand_man:{keywords:["male","boy","man"],char:'🙋‍♂️',fitzpatrick_scale:true,category:"people"},pouting_woman:{keywords:["female","girl","woman"],char:'🙎',fitzpatrick_scale:true,category:"people"},pouting_man:{keywords:["male","boy","man"],char:'🙎‍♂️',fitzpatrick_scale:true,category:"people"},frowning_woman:{keywords:["female","girl","woman","sad","depressed","discouraged","unhappy"],char:'🙍',fitzpatrick_scale:true,category:"people"},frowning_man:{keywords:["male","boy","man","sad","depressed","discouraged","unhappy"],char:'🙍‍♂️',fitzpatrick_scale:true,category:"people"},haircut_woman:{keywords:["female","girl","woman"],char:'💇',fitzpatrick_scale:true,category:"people"},haircut_man:{keywords:["male","boy","man"],char:'💇‍♂️',fitzpatrick_scale:true,category:"people"},massage_woman:{keywords:["female","girl","woman","head"],char:'💆',fitzpatrick_scale:true,category:"people"},massage_man:{keywords:["male","boy","man","head"],char:'💆‍♂️',fitzpatrick_scale:true,category:"people"},woman_in_steamy_room:{keywords:["female","woman","spa","steamroom","sauna"],char:'🧖‍♀️',fitzpatrick_scale:true,category:"people"},man_in_steamy_room:{keywords:["male","man","spa","steamroom","sauna"],char:'🧖‍♂️',fitzpatrick_scale:true,category:"people"},couple_with_heart_woman_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:'💑',fitzpatrick_scale:false,category:"people"},couple_with_heart_woman_woman:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:'👩‍❤️‍👩',fitzpatrick_scale:false,category:"people"},couple_with_heart_man_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:'👨‍❤️‍👨',fitzpatrick_scale:false,category:"people"},couplekiss_man_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:'💏',fitzpatrick_scale:false,category:"people"},couplekiss_woman_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:'👩‍❤️‍💋‍👩',fitzpatrick_scale:false,category:"people"},couplekiss_man_man:{keywords:["pair","valentines","love","like","dating","marriage"],char:'👨‍❤️‍💋‍👨',fitzpatrick_scale:false,category:"people"},family_man_woman_boy:{keywords:["home","parents","child","mom","dad","father","mother","people","human"],char:'👪',fitzpatrick_scale:false,category:"people"},family_man_woman_girl:{keywords:["home","parents","people","human","child"],char:'👨‍👩‍👧',fitzpatrick_scale:false,category:"people"},family_man_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:'👨‍👩‍👧‍👦',fitzpatrick_scale:false,category:"people"},family_man_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:'👨‍👩‍👦‍👦',fitzpatrick_scale:false,category:"people"},family_man_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:'👨‍👩‍👧‍👧',fitzpatrick_scale:false,category:"people"},family_woman_woman_boy:{keywords:["home","parents","people","human","children"],char:'👩‍👩‍👦',fitzpatrick_scale:false,category:"people"},family_woman_woman_girl:{keywords:["home","parents","people","human","children"],char:'👩‍👩‍👧',fitzpatrick_scale:false,category:"people"},family_woman_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:'👩‍👩‍👧‍👦',fitzpatrick_scale:false,category:"people"},family_woman_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:'👩‍👩‍👦‍👦',fitzpatrick_scale:false,category:"people"},family_woman_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:'👩‍👩‍👧‍👧',fitzpatrick_scale:false,category:"people"},family_man_man_boy:{keywords:["home","parents","people","human","children"],char:'👨‍👨‍👦',fitzpatrick_scale:false,category:"people"},family_man_man_girl:{keywords:["home","parents","people","human","children"],char:'👨‍👨‍👧',fitzpatrick_scale:false,category:"people"},family_man_man_girl_boy:{keywords:["home","parents","people","human","children"],char:'👨‍👨‍👧‍👦',fitzpatrick_scale:false,category:"people"},family_man_man_boy_boy:{keywords:["home","parents","people","human","children"],char:'👨‍👨‍👦‍👦',fitzpatrick_scale:false,category:"people"},family_man_man_girl_girl:{keywords:["home","parents","people","human","children"],char:'👨‍👨‍👧‍👧',fitzpatrick_scale:false,category:"people"},family_woman_boy:{keywords:["home","parent","people","human","child"],char:'👩‍👦',fitzpatrick_scale:false,category:"people"},family_woman_girl:{keywords:["home","parent","people","human","child"],char:'👩‍👧',fitzpatrick_scale:false,category:"people"},family_woman_girl_boy:{keywords:["home","parent","people","human","children"],char:'👩‍👧‍👦',fitzpatrick_scale:false,category:"people"},family_woman_boy_boy:{keywords:["home","parent","people","human","children"],char:'👩‍👦‍👦',fitzpatrick_scale:false,category:"people"},family_woman_girl_girl:{keywords:["home","parent","people","human","children"],char:'👩‍👧‍👧',fitzpatrick_scale:false,category:"people"},family_man_boy:{keywords:["home","parent","people","human","child"],char:'👨‍👦',fitzpatrick_scale:false,category:"people"},family_man_girl:{keywords:["home","parent","people","human","child"],char:'👨‍👧',fitzpatrick_scale:false,category:"people"},family_man_girl_boy:{keywords:["home","parent","people","human","children"],char:'👨‍👧‍👦',fitzpatrick_scale:false,category:"people"},family_man_boy_boy:{keywords:["home","parent","people","human","children"],char:'👨‍👦‍👦',fitzpatrick_scale:false,category:"people"},family_man_girl_girl:{keywords:["home","parent","people","human","children"],char:'👨‍👧‍👧',fitzpatrick_scale:false,category:"people"},yarn:{keywords:["ball","crochet","knit"],char:'🧶',fitzpatrick_scale:false,category:"people"},thread:{keywords:["needle","sewing","spool","string"],char:'🧵',fitzpatrick_scale:false,category:"people"},coat:{keywords:["jacket"],char:'🧥',fitzpatrick_scale:false,category:"people"},labcoat:{keywords:["doctor","experiment","scientist","chemist"],char:'🥼',fitzpatrick_scale:false,category:"people"},womans_clothes:{keywords:["fashion","shopping_bags","female"],char:'👚',fitzpatrick_scale:false,category:"people"},tshirt:{keywords:["fashion","cloth","casual","shirt","tee"],char:'👕',fitzpatrick_scale:false,category:"people"},jeans:{keywords:["fashion","shopping"],char:'👖',fitzpatrick_scale:false,category:"people"},necktie:{keywords:["shirt","suitup","formal","fashion","cloth","business"],char:'👔',fitzpatrick_scale:false,category:"people"},dress:{keywords:["clothes","fashion","shopping"],char:'👗',fitzpatrick_scale:false,category:"people"},bikini:{keywords:["swimming","female","woman","girl","fashion","beach","summer"],char:'👙',fitzpatrick_scale:false,category:"people"},kimono:{keywords:["dress","fashion","women","female","japanese"],char:'👘',fitzpatrick_scale:false,category:"people"},lipstick:{keywords:["female","girl","fashion","woman"],char:'💄',fitzpatrick_scale:false,category:"people"},kiss:{keywords:["face","lips","love","like","affection","valentines"],char:'💋',fitzpatrick_scale:false,category:"people"},footprints:{keywords:["feet","tracking","walking","beach"],char:'👣',fitzpatrick_scale:false,category:"people"},flat_shoe:{keywords:["ballet","slip-on","slipper"],char:'🥿',fitzpatrick_scale:false,category:"people"},high_heel:{keywords:["fashion","shoes","female","pumps","stiletto"],char:'👠',fitzpatrick_scale:false,category:"people"},sandal:{keywords:["shoes","fashion","flip flops"],char:'👡',fitzpatrick_scale:false,category:"people"},boot:{keywords:["shoes","fashion"],char:'👢',fitzpatrick_scale:false,category:"people"},mans_shoe:{keywords:["fashion","male"],char:'👞',fitzpatrick_scale:false,category:"people"},athletic_shoe:{keywords:["shoes","sports","sneakers"],char:'👟',fitzpatrick_scale:false,category:"people"},hiking_boot:{keywords:["backpacking","camping","hiking"],char:'🥾',fitzpatrick_scale:false,category:"people"},socks:{keywords:["stockings","clothes"],char:'🧦',fitzpatrick_scale:false,category:"people"},gloves:{keywords:["hands","winter","clothes"],char:'🧤',fitzpatrick_scale:false,category:"people"},scarf:{keywords:["neck","winter","clothes"],char:'🧣',fitzpatrick_scale:false,category:"people"},womans_hat:{keywords:["fashion","accessories","female","lady","spring"],char:'👒',fitzpatrick_scale:false,category:"people"},tophat:{keywords:["magic","gentleman","classy","circus"],char:'🎩',fitzpatrick_scale:false,category:"people"},billed_hat:{keywords:["cap","baseball"],char:'🧢',fitzpatrick_scale:false,category:"people"},rescue_worker_helmet:{keywords:["construction","build"],char:'⛑',fitzpatrick_scale:false,category:"people"},mortar_board:{keywords:["school","college","degree","university","graduation","cap","hat","legal","learn","education"],char:'🎓',fitzpatrick_scale:false,category:"people"},crown:{keywords:["king","kod","leader","royalty","lord"],char:'👑',fitzpatrick_scale:false,category:"people"},school_satchel:{keywords:["student","education","bag","backpack"],char:'🎒',fitzpatrick_scale:false,category:"people"},luggage:{keywords:["packing","travel"],char:'🧳',fitzpatrick_scale:false,category:"people"},pouch:{keywords:["bag","accessories","shopping"],char:'👝',fitzpatrick_scale:false,category:"people"},purse:{keywords:["fashion","accessories","money","sales","shopping"],char:'👛',fitzpatrick_scale:false,category:"people"},handbag:{keywords:["fashion","accessory","accessories","shopping"],char:'👜',fitzpatrick_scale:false,category:"people"},briefcase:{keywords:["business","documents","work","law","legal","job","career"],char:'💼',fitzpatrick_scale:false,category:"people"},eyeglasses:{keywords:["fashion","accessories","eyesight","nerdy","dork","geek"],char:'👓',fitzpatrick_scale:false,category:"people"},dark_sunglasses:{keywords:["face","cool","accessories"],char:'🕶',fitzpatrick_scale:false,category:"people"},goggles:{keywords:["eyes","protection","safety"],char:'🥽',fitzpatrick_scale:false,category:"people"},ring:{keywords:["wedding","propose","marriage","valentines","diamond","fashion","jewelry","gem","engagement"],char:'💍',fitzpatrick_scale:false,category:"people"},closed_umbrella:{keywords:["weather","rain","drizzle"],char:'🌂',fitzpatrick_scale:false,category:"people"},dog:{keywords:["animal","friend","nature","woof","puppy","pet","faithful"],char:'🐶',fitzpatrick_scale:false,category:"animals_and_nature"},cat:{keywords:["animal","meow","nature","pet","kitten"],char:'🐱',fitzpatrick_scale:false,category:"animals_and_nature"},mouse:{keywords:["animal","nature","cheese_wedge","rodent"],char:'🐭',fitzpatrick_scale:false,category:"animals_and_nature"},hamster:{keywords:["animal","nature"],char:'🐹',fitzpatrick_scale:false,category:"animals_and_nature"},rabbit:{keywords:["animal","nature","pet","spring","magic","bunny"],char:'🐰',fitzpatrick_scale:false,category:"animals_and_nature"},fox_face:{keywords:["animal","nature","face"],char:'🦊',fitzpatrick_scale:false,category:"animals_and_nature"},bear:{keywords:["animal","nature","wild"],char:'🐻',fitzpatrick_scale:false,category:"animals_and_nature"},panda_face:{keywords:["animal","nature","panda"],char:'🐼',fitzpatrick_scale:false,category:"animals_and_nature"},koala:{keywords:["animal","nature"],char:'🐨',fitzpatrick_scale:false,category:"animals_and_nature"},tiger:{keywords:["animal","cat","danger","wild","nature","roar"],char:'🐯',fitzpatrick_scale:false,category:"animals_and_nature"},lion:{keywords:["animal","nature"],char:'🦁',fitzpatrick_scale:false,category:"animals_and_nature"},cow:{keywords:["beef","ox","animal","nature","moo","milk"],char:'🐮',fitzpatrick_scale:false,category:"animals_and_nature"},pig:{keywords:["animal","oink","nature"],char:'🐷',fitzpatrick_scale:false,category:"animals_and_nature"},pig_nose:{keywords:["animal","oink"],char:'🐽',fitzpatrick_scale:false,category:"animals_and_nature"},frog:{keywords:["animal","nature","croak","toad"],char:'🐸',fitzpatrick_scale:false,category:"animals_and_nature"},squid:{keywords:["animal","nature","ocean","sea"],char:'🦑',fitzpatrick_scale:false,category:"animals_and_nature"},octopus:{keywords:["animal","creature","ocean","sea","nature","beach"],char:'🐙',fitzpatrick_scale:false,category:"animals_and_nature"},shrimp:{keywords:["animal","ocean","nature","seafood"],char:'🦐',fitzpatrick_scale:false,category:"animals_and_nature"},monkey_face:{keywords:["animal","nature","circus"],char:'🐵',fitzpatrick_scale:false,category:"animals_and_nature"},gorilla:{keywords:["animal","nature","circus"],char:'🦍',fitzpatrick_scale:false,category:"animals_and_nature"},see_no_evil:{keywords:["monkey","animal","nature","haha"],char:'🙈',fitzpatrick_scale:false,category:"animals_and_nature"},hear_no_evil:{keywords:["animal","monkey","nature"],char:'🙉',fitzpatrick_scale:false,category:"animals_and_nature"},speak_no_evil:{keywords:["monkey","animal","nature","omg"],char:'🙊',fitzpatrick_scale:false,category:"animals_and_nature"},monkey:{keywords:["animal","nature","banana","circus"],char:'🐒',fitzpatrick_scale:false,category:"animals_and_nature"},chicken:{keywords:["animal","cluck","nature","bird"],char:'🐔',fitzpatrick_scale:false,category:"animals_and_nature"},penguin:{keywords:["animal","nature"],char:'🐧',fitzpatrick_scale:false,category:"animals_and_nature"},bird:{keywords:["animal","nature","fly","tweet","spring"],char:'🐦',fitzpatrick_scale:false,category:"animals_and_nature"},baby_chick:{keywords:["animal","chicken","bird"],char:'🐤',fitzpatrick_scale:false,category:"animals_and_nature"},hatching_chick:{keywords:["animal","chicken","egg","born","baby","bird"],char:'🐣',fitzpatrick_scale:false,category:"animals_and_nature"},hatched_chick:{keywords:["animal","chicken","baby","bird"],char:'🐥',fitzpatrick_scale:false,category:"animals_and_nature"},duck:{keywords:["animal","nature","bird","mallard"],char:'🦆',fitzpatrick_scale:false,category:"animals_and_nature"},eagle:{keywords:["animal","nature","bird"],char:'🦅',fitzpatrick_scale:false,category:"animals_and_nature"},owl:{keywords:["animal","nature","bird","hoot"],char:'🦉',fitzpatrick_scale:false,category:"animals_and_nature"},bat:{keywords:["animal","nature","blind","vampire"],char:'🦇',fitzpatrick_scale:false,category:"animals_and_nature"},wolf:{keywords:["animal","nature","wild"],char:'🐺',fitzpatrick_scale:false,category:"animals_and_nature"},boar:{keywords:["animal","nature"],char:'🐗',fitzpatrick_scale:false,category:"animals_and_nature"},horse:{keywords:["animal","brown","nature"],char:'🐴',fitzpatrick_scale:false,category:"animals_and_nature"},unicorn:{keywords:["animal","nature","mystical"],char:'🦄',fitzpatrick_scale:false,category:"animals_and_nature"},honeybee:{keywords:["animal","insect","nature","bug","spring","honey"],char:'🐝',fitzpatrick_scale:false,category:"animals_and_nature"},bug:{keywords:["animal","insect","nature","worm"],char:'🐛',fitzpatrick_scale:false,category:"animals_and_nature"},butterfly:{keywords:["animal","insect","nature","caterpillar"],char:'🦋',fitzpatrick_scale:false,category:"animals_and_nature"},snail:{keywords:["slow","animal","shell"],char:'🐌',fitzpatrick_scale:false,category:"animals_and_nature"},beetle:{keywords:["animal","insect","nature","ladybug"],char:'🐞',fitzpatrick_scale:false,category:"animals_and_nature"},ant:{keywords:["animal","insect","nature","bug"],char:'🐜',fitzpatrick_scale:false,category:"animals_and_nature"},grasshopper:{keywords:["animal","cricket","chirp"],char:'🦗',fitzpatrick_scale:false,category:"animals_and_nature"},spider:{keywords:["animal","arachnid"],char:'🕷',fitzpatrick_scale:false,category:"animals_and_nature"},scorpion:{keywords:["animal","arachnid"],char:'🦂',fitzpatrick_scale:false,category:"animals_and_nature"},crab:{keywords:["animal","crustacean"],char:'🦀',fitzpatrick_scale:false,category:"animals_and_nature"},snake:{keywords:["animal","evil","nature","hiss","python"],char:'🐍',fitzpatrick_scale:false,category:"animals_and_nature"},lizard:{keywords:["animal","nature","reptile"],char:'🦎',fitzpatrick_scale:false,category:"animals_and_nature"},"t-rex":{keywords:["animal","nature","dinosaur","tyrannosaurus","extinct"],char:'🦖',fitzpatrick_scale:false,category:"animals_and_nature"},sauropod:{keywords:["animal","nature","dinosaur","brachiosaurus","brontosaurus","diplodocus","extinct"],char:'🦕',fitzpatrick_scale:false,category:"animals_and_nature"},turtle:{keywords:["animal","slow","nature","tortoise"],char:'🐢',fitzpatrick_scale:false,category:"animals_and_nature"},tropical_fish:{keywords:["animal","swim","ocean","beach","nemo"],char:'🐠',fitzpatrick_scale:false,category:"animals_and_nature"},fish:{keywords:["animal","food","nature"],char:'🐟',fitzpatrick_scale:false,category:"animals_and_nature"},blowfish:{keywords:["animal","nature","food","sea","ocean"],char:'🐡',fitzpatrick_scale:false,category:"animals_and_nature"},dolphin:{keywords:["animal","nature","fish","sea","ocean","flipper","fins","beach"],char:'🐬',fitzpatrick_scale:false,category:"animals_and_nature"},shark:{keywords:["animal","nature","fish","sea","ocean","jaws","fins","beach"],char:'🦈',fitzpatrick_scale:false,category:"animals_and_nature"},whale:{keywords:["animal","nature","sea","ocean"],char:'🐳',fitzpatrick_scale:false,category:"animals_and_nature"},whale2:{keywords:["animal","nature","sea","ocean"],char:'🐋',fitzpatrick_scale:false,category:"animals_and_nature"},crocodile:{keywords:["animal","nature","reptile","lizard","alligator"],char:'🐊',fitzpatrick_scale:false,category:"animals_and_nature"},leopard:{keywords:["animal","nature"],char:'🐆',fitzpatrick_scale:false,category:"animals_and_nature"},zebra:{keywords:["animal","nature","stripes","safari"],char:'🦓',fitzpatrick_scale:false,category:"animals_and_nature"},tiger2:{keywords:["animal","nature","roar"],char:'🐅',fitzpatrick_scale:false,category:"animals_and_nature"},water_buffalo:{keywords:["animal","nature","ox","cow"],char:'🐃',fitzpatrick_scale:false,category:"animals_and_nature"},ox:{keywords:["animal","cow","beef"],char:'🐂',fitzpatrick_scale:false,category:"animals_and_nature"},cow2:{keywords:["beef","ox","animal","nature","moo","milk"],char:'🐄',fitzpatrick_scale:false,category:"animals_and_nature"},deer:{keywords:["animal","nature","horns","venison"],char:'🦌',fitzpatrick_scale:false,category:"animals_and_nature"},dromedary_camel:{keywords:["animal","hot","desert","hump"],char:'🐪',fitzpatrick_scale:false,category:"animals_and_nature"},camel:{keywords:["animal","nature","hot","desert","hump"],char:'🐫',fitzpatrick_scale:false,category:"animals_and_nature"},giraffe:{keywords:["animal","nature","spots","safari"],char:'🦒',fitzpatrick_scale:false,category:"animals_and_nature"},elephant:{keywords:["animal","nature","nose","th","circus"],char:'🐘',fitzpatrick_scale:false,category:"animals_and_nature"},rhinoceros:{keywords:["animal","nature","horn"],char:'🦏',fitzpatrick_scale:false,category:"animals_and_nature"},goat:{keywords:["animal","nature"],char:'🐐',fitzpatrick_scale:false,category:"animals_and_nature"},ram:{keywords:["animal","sheep","nature"],char:'🐏',fitzpatrick_scale:false,category:"animals_and_nature"},sheep:{keywords:["animal","nature","wool","shipit"],char:'🐑',fitzpatrick_scale:false,category:"animals_and_nature"},racehorse:{keywords:["animal","gamble","luck"],char:'🐎',fitzpatrick_scale:false,category:"animals_and_nature"},pig2:{keywords:["animal","nature"],char:'🐖',fitzpatrick_scale:false,category:"animals_and_nature"},rat:{keywords:["animal","mouse","rodent"],char:'🐀',fitzpatrick_scale:false,category:"animals_and_nature"},mouse2:{keywords:["animal","nature","rodent"],char:'🐁',fitzpatrick_scale:false,category:"animals_and_nature"},rooster:{keywords:["animal","nature","chicken"],char:'🐓',fitzpatrick_scale:false,category:"animals_and_nature"},turkey:{keywords:["animal","bird"],char:'🦃',fitzpatrick_scale:false,category:"animals_and_nature"},dove:{keywords:["animal","bird"],char:'🕊',fitzpatrick_scale:false,category:"animals_and_nature"},dog2:{keywords:["animal","nature","friend","doge","pet","faithful"],char:'🐕',fitzpatrick_scale:false,category:"animals_and_nature"},poodle:{keywords:["dog","animal","101","nature","pet"],char:'🐩',fitzpatrick_scale:false,category:"animals_and_nature"},cat2:{keywords:["animal","meow","pet","cats"],char:'🐈',fitzpatrick_scale:false,category:"animals_and_nature"},rabbit2:{keywords:["animal","nature","pet","magic","spring"],char:'🐇',fitzpatrick_scale:false,category:"animals_and_nature"},chipmunk:{keywords:["animal","nature","rodent","squirrel"],char:'🐿',fitzpatrick_scale:false,category:"animals_and_nature"},hedgehog:{keywords:["animal","nature","spiny"],char:'🦔',fitzpatrick_scale:false,category:"animals_and_nature"},raccoon:{keywords:["animal","nature"],char:'🦝',fitzpatrick_scale:false,category:"animals_and_nature"},llama:{keywords:["animal","nature","alpaca"],char:'🦙',fitzpatrick_scale:false,category:"animals_and_nature"},hippopotamus:{keywords:["animal","nature"],char:'🦛',fitzpatrick_scale:false,category:"animals_and_nature"},kangaroo:{keywords:["animal","nature","australia","joey","hop","marsupial"],char:'🦘',fitzpatrick_scale:false,category:"animals_and_nature"},badger:{keywords:["animal","nature","honey"],char:'🦡',fitzpatrick_scale:false,category:"animals_and_nature"},swan:{keywords:["animal","nature","bird"],char:'🦢',fitzpatrick_scale:false,category:"animals_and_nature"},peacock:{keywords:["animal","nature","peahen","bird"],char:'🦚',fitzpatrick_scale:false,category:"animals_and_nature"},parrot:{keywords:["animal","nature","bird","pirate","talk"],char:'🦜',fitzpatrick_scale:false,category:"animals_and_nature"},lobster:{keywords:["animal","nature","bisque","claws","seafood"],char:'🦞',fitzpatrick_scale:false,category:"animals_and_nature"},mosquito:{keywords:["animal","nature","insect","malaria"],char:'🦟',fitzpatrick_scale:false,category:"animals_and_nature"},paw_prints:{keywords:["animal","tracking","footprints","dog","cat","pet","feet"],char:'🐾',fitzpatrick_scale:false,category:"animals_and_nature"},dragon:{keywords:["animal","myth","nature","chinese","green"],char:'🐉',fitzpatrick_scale:false,category:"animals_and_nature"},dragon_face:{keywords:["animal","myth","nature","chinese","green"],char:'🐲',fitzpatrick_scale:false,category:"animals_and_nature"},cactus:{keywords:["vegetable","plant","nature"],char:'🌵',fitzpatrick_scale:false,category:"animals_and_nature"},christmas_tree:{keywords:["festival","vacation","december","xmas","celebration"],char:'🎄',fitzpatrick_scale:false,category:"animals_and_nature"},evergreen_tree:{keywords:["plant","nature"],char:'🌲',fitzpatrick_scale:false,category:"animals_and_nature"},deciduous_tree:{keywords:["plant","nature"],char:'🌳',fitzpatrick_scale:false,category:"animals_and_nature"},palm_tree:{keywords:["plant","vegetable","nature","summer","beach","mojito","tropical"],char:'🌴',fitzpatrick_scale:false,category:"animals_and_nature"},seedling:{keywords:["plant","nature","grass","lawn","spring"],char:'🌱',fitzpatrick_scale:false,category:"animals_and_nature"},herb:{keywords:["vegetable","plant","medicine","weed","grass","lawn"],char:'🌿',fitzpatrick_scale:false,category:"animals_and_nature"},shamrock:{keywords:["vegetable","plant","nature","irish","clover"],char:'☘',fitzpatrick_scale:false,category:"animals_and_nature"},four_leaf_clover:{keywords:["vegetable","plant","nature","lucky","irish"],char:'🍀',fitzpatrick_scale:false,category:"animals_and_nature"},bamboo:{keywords:["plant","nature","vegetable","panda","pine_decoration"],char:'🎍',fitzpatrick_scale:false,category:"animals_and_nature"},tanabata_tree:{keywords:["plant","nature","branch","summer"],char:'🎋',fitzpatrick_scale:false,category:"animals_and_nature"},leaves:{keywords:["nature","plant","tree","vegetable","grass","lawn","spring"],char:'🍃',fitzpatrick_scale:false,category:"animals_and_nature"},fallen_leaf:{keywords:["nature","plant","vegetable","leaves"],char:'🍂',fitzpatrick_scale:false,category:"animals_and_nature"},maple_leaf:{keywords:["nature","plant","vegetable","ca","fall"],char:'🍁',fitzpatrick_scale:false,category:"animals_and_nature"},ear_of_rice:{keywords:["nature","plant"],char:'🌾',fitzpatrick_scale:false,category:"animals_and_nature"},hibiscus:{keywords:["plant","vegetable","flowers","beach"],char:'🌺',fitzpatrick_scale:false,category:"animals_and_nature"},sunflower:{keywords:["nature","plant","fall"],char:'🌻',fitzpatrick_scale:false,category:"animals_and_nature"},rose:{keywords:["flowers","valentines","love","spring"],char:'🌹',fitzpatrick_scale:false,category:"animals_and_nature"},wilted_flower:{keywords:["plant","nature","flower"],char:'🥀',fitzpatrick_scale:false,category:"animals_and_nature"},tulip:{keywords:["flowers","plant","nature","summer","spring"],char:'🌷',fitzpatrick_scale:false,category:"animals_and_nature"},blossom:{keywords:["nature","flowers","yellow"],char:'🌼',fitzpatrick_scale:false,category:"animals_and_nature"},cherry_blossom:{keywords:["nature","plant","spring","flower"],char:'🌸',fitzpatrick_scale:false,category:"animals_and_nature"},bouquet:{keywords:["flowers","nature","spring"],char:'💐',fitzpatrick_scale:false,category:"animals_and_nature"},mushroom:{keywords:["plant","vegetable"],char:'🍄',fitzpatrick_scale:false,category:"animals_and_nature"},chestnut:{keywords:["food","squirrel"],char:'🌰',fitzpatrick_scale:false,category:"animals_and_nature"},jack_o_lantern:{keywords:["halloween","light","pumpkin","creepy","fall"],char:'🎃',fitzpatrick_scale:false,category:"animals_and_nature"},shell:{keywords:["nature","sea","beach"],char:'🐚',fitzpatrick_scale:false,category:"animals_and_nature"},spider_web:{keywords:["animal","insect","arachnid","silk"],char:'🕸',fitzpatrick_scale:false,category:"animals_and_nature"},earth_americas:{keywords:["globe","world","USA","international"],char:'🌎',fitzpatrick_scale:false,category:"animals_and_nature"},earth_africa:{keywords:["globe","world","international"],char:'🌍',fitzpatrick_scale:false,category:"animals_and_nature"},earth_asia:{keywords:["globe","world","east","international"],char:'🌏',fitzpatrick_scale:false,category:"animals_and_nature"},full_moon:{keywords:["nature","yellow","twilight","planet","space","night","evening","sleep"],char:'🌕',fitzpatrick_scale:false,category:"animals_and_nature"},waning_gibbous_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep","waxing_gibbous_moon"],char:'🌖',fitzpatrick_scale:false,category:"animals_and_nature"},last_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌗',fitzpatrick_scale:false,category:"animals_and_nature"},waning_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌘',fitzpatrick_scale:false,category:"animals_and_nature"},new_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌑',fitzpatrick_scale:false,category:"animals_and_nature"},waxing_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌒',fitzpatrick_scale:false,category:"animals_and_nature"},first_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌓',fitzpatrick_scale:false,category:"animals_and_nature"},waxing_gibbous_moon:{keywords:["nature","night","sky","gray","twilight","planet","space","evening","sleep"],char:'🌔',fitzpatrick_scale:false,category:"animals_and_nature"},new_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌚',fitzpatrick_scale:false,category:"animals_and_nature"},full_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌝',fitzpatrick_scale:false,category:"animals_and_nature"},first_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌛',fitzpatrick_scale:false,category:"animals_and_nature"},last_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'🌜',fitzpatrick_scale:false,category:"animals_and_nature"},sun_with_face:{keywords:["nature","morning","sky"],char:'🌞',fitzpatrick_scale:false,category:"animals_and_nature"},crescent_moon:{keywords:["night","sleep","sky","evening","magic"],char:'🌙',fitzpatrick_scale:false,category:"animals_and_nature"},star:{keywords:["night","yellow"],char:'⭐',fitzpatrick_scale:false,category:"animals_and_nature"},star2:{keywords:["night","sparkle","awesome","good","magic"],char:'🌟',fitzpatrick_scale:false,category:"animals_and_nature"},dizzy:{keywords:["star","sparkle","shoot","magic"],char:'💫',fitzpatrick_scale:false,category:"animals_and_nature"},sparkles:{keywords:["stars","shine","shiny","cool","awesome","good","magic"],char:'✨',fitzpatrick_scale:false,category:"animals_and_nature"},comet:{keywords:["space"],char:'☄',fitzpatrick_scale:false,category:"animals_and_nature"},sunny:{keywords:["weather","nature","brightness","summer","beach","spring"],char:'☀️',fitzpatrick_scale:false,category:"animals_and_nature"},sun_behind_small_cloud:{keywords:["weather"],char:'🌤',fitzpatrick_scale:false,category:"animals_and_nature"},partly_sunny:{keywords:["weather","nature","cloudy","morning","fall","spring"],char:'⛅',fitzpatrick_scale:false,category:"animals_and_nature"},sun_behind_large_cloud:{keywords:["weather"],char:'🌥',fitzpatrick_scale:false,category:"animals_and_nature"},sun_behind_rain_cloud:{keywords:["weather"],char:'🌦',fitzpatrick_scale:false,category:"animals_and_nature"},cloud:{keywords:["weather","sky"],char:'☁️',fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_rain:{keywords:["weather"],char:'🌧',fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_lightning_and_rain:{keywords:["weather","lightning"],char:'⛈',fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_lightning:{keywords:["weather","thunder"],char:'🌩',fitzpatrick_scale:false,category:"animals_and_nature"},zap:{keywords:["thunder","weather","lightning bolt","fast"],char:'⚡',fitzpatrick_scale:false,category:"animals_and_nature"},fire:{keywords:["hot","cook","flame"],char:'🔥',fitzpatrick_scale:false,category:"animals_and_nature"},boom:{keywords:["bomb","explode","explosion","collision","blown"],char:'💥',fitzpatrick_scale:false,category:"animals_and_nature"},snowflake:{keywords:["winter","season","cold","weather","christmas","xmas"],char:'❄️',fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_snow:{keywords:["weather"],char:'🌨',fitzpatrick_scale:false,category:"animals_and_nature"},snowman:{keywords:["winter","season","cold","weather","christmas","xmas","frozen","without_snow"],char:'⛄',fitzpatrick_scale:false,category:"animals_and_nature"},snowman_with_snow:{keywords:["winter","season","cold","weather","christmas","xmas","frozen"],char:'☃',fitzpatrick_scale:false,category:"animals_and_nature"},wind_face:{keywords:["gust","air"],char:'🌬',fitzpatrick_scale:false,category:"animals_and_nature"},dash:{keywords:["wind","air","fast","shoo","fart","smoke","puff"],char:'💨',fitzpatrick_scale:false,category:"animals_and_nature"},tornado:{keywords:["weather","cyclone","twister"],char:'🌪',fitzpatrick_scale:false,category:"animals_and_nature"},fog:{keywords:["weather"],char:'🌫',fitzpatrick_scale:false,category:"animals_and_nature"},open_umbrella:{keywords:["weather","spring"],char:'☂',fitzpatrick_scale:false,category:"animals_and_nature"},umbrella:{keywords:["rainy","weather","spring"],char:'☔',fitzpatrick_scale:false,category:"animals_and_nature"},droplet:{keywords:["water","drip","faucet","spring"],char:'💧',fitzpatrick_scale:false,category:"animals_and_nature"},sweat_drops:{keywords:["water","drip","oops"],char:'💦',fitzpatrick_scale:false,category:"animals_and_nature"},ocean:{keywords:["sea","water","wave","nature","tsunami","disaster"],char:'🌊',fitzpatrick_scale:false,category:"animals_and_nature"},green_apple:{keywords:["fruit","nature"],char:'🍏',fitzpatrick_scale:false,category:"food_and_drink"},apple:{keywords:["fruit","mac","school"],char:'🍎',fitzpatrick_scale:false,category:"food_and_drink"},pear:{keywords:["fruit","nature","food"],char:'🍐',fitzpatrick_scale:false,category:"food_and_drink"},tangerine:{keywords:["food","fruit","nature","orange"],char:'🍊',fitzpatrick_scale:false,category:"food_and_drink"},lemon:{keywords:["fruit","nature"],char:'🍋',fitzpatrick_scale:false,category:"food_and_drink"},banana:{keywords:["fruit","food","monkey"],char:'🍌',fitzpatrick_scale:false,category:"food_and_drink"},watermelon:{keywords:["fruit","food","picnic","summer"],char:'🍉',fitzpatrick_scale:false,category:"food_and_drink"},grapes:{keywords:["fruit","food","wine"],char:'🍇',fitzpatrick_scale:false,category:"food_and_drink"},strawberry:{keywords:["fruit","food","nature"],char:'🍓',fitzpatrick_scale:false,category:"food_and_drink"},melon:{keywords:["fruit","nature","food"],char:'🍈',fitzpatrick_scale:false,category:"food_and_drink"},cherries:{keywords:["food","fruit"],char:'🍒',fitzpatrick_scale:false,category:"food_and_drink"},peach:{keywords:["fruit","nature","food"],char:'🍑',fitzpatrick_scale:false,category:"food_and_drink"},pineapple:{keywords:["fruit","nature","food"],char:'🍍',fitzpatrick_scale:false,category:"food_and_drink"},coconut:{keywords:["fruit","nature","food","palm"],char:'🥥',fitzpatrick_scale:false,category:"food_and_drink"},kiwi_fruit:{keywords:["fruit","food"],char:'🥝',fitzpatrick_scale:false,category:"food_and_drink"},mango:{keywords:["fruit","food","tropical"],char:'🥭',fitzpatrick_scale:false,category:"food_and_drink"},avocado:{keywords:["fruit","food"],char:'🥑',fitzpatrick_scale:false,category:"food_and_drink"},broccoli:{keywords:["fruit","food","vegetable"],char:'🥦',fitzpatrick_scale:false,category:"food_and_drink"},tomato:{keywords:["fruit","vegetable","nature","food"],char:'🍅',fitzpatrick_scale:false,category:"food_and_drink"},eggplant:{keywords:["vegetable","nature","food","aubergine"],char:'🍆',fitzpatrick_scale:false,category:"food_and_drink"},cucumber:{keywords:["fruit","food","pickle"],char:'🥒',fitzpatrick_scale:false,category:"food_and_drink"},carrot:{keywords:["vegetable","food","orange"],char:'🥕',fitzpatrick_scale:false,category:"food_and_drink"},hot_pepper:{keywords:["food","spicy","chilli","chili"],char:'🌶',fitzpatrick_scale:false,category:"food_and_drink"},potato:{keywords:["food","tuber","vegatable","starch"],char:'🥔',fitzpatrick_scale:false,category:"food_and_drink"},corn:{keywords:["food","vegetable","plant"],char:'🌽',fitzpatrick_scale:false,category:"food_and_drink"},leafy_greens:{keywords:["food","vegetable","plant","bok choy","cabbage","kale","lettuce"],char:'🥬',fitzpatrick_scale:false,category:"food_and_drink"},sweet_potato:{keywords:["food","nature"],char:'🍠',fitzpatrick_scale:false,category:"food_and_drink"},peanuts:{keywords:["food","nut"],char:'🥜',fitzpatrick_scale:false,category:"food_and_drink"},honey_pot:{keywords:["bees","sweet","kitchen"],char:'🍯',fitzpatrick_scale:false,category:"food_and_drink"},croissant:{keywords:["food","bread","french"],char:'🥐',fitzpatrick_scale:false,category:"food_and_drink"},bread:{keywords:["food","wheat","breakfast","toast"],char:'🍞',fitzpatrick_scale:false,category:"food_and_drink"},baguette_bread:{keywords:["food","bread","french"],char:'🥖',fitzpatrick_scale:false,category:"food_and_drink"},bagel:{keywords:["food","bread","bakery","schmear"],char:'🥯',fitzpatrick_scale:false,category:"food_and_drink"},pretzel:{keywords:["food","bread","twisted"],char:'🥨',fitzpatrick_scale:false,category:"food_and_drink"},cheese:{keywords:["food","chadder"],char:'🧀',fitzpatrick_scale:false,category:"food_and_drink"},egg:{keywords:["food","chicken","breakfast"],char:'🥚',fitzpatrick_scale:false,category:"food_and_drink"},bacon:{keywords:["food","breakfast","pork","pig","meat"],char:'🥓',fitzpatrick_scale:false,category:"food_and_drink"},steak:{keywords:["food","cow","meat","cut","chop","lambchop","porkchop"],char:'🥩',fitzpatrick_scale:false,category:"food_and_drink"},pancakes:{keywords:["food","breakfast","flapjacks","hotcakes"],char:'🥞',fitzpatrick_scale:false,category:"food_and_drink"},poultry_leg:{keywords:["food","meat","drumstick","bird","chicken","turkey"],char:'🍗',fitzpatrick_scale:false,category:"food_and_drink"},meat_on_bone:{keywords:["good","food","drumstick"],char:'🍖',fitzpatrick_scale:false,category:"food_and_drink"},bone:{keywords:["skeleton"],char:'🦴',fitzpatrick_scale:false,category:"food_and_drink"},fried_shrimp:{keywords:["food","animal","appetizer","summer"],char:'🍤',fitzpatrick_scale:false,category:"food_and_drink"},fried_egg:{keywords:["food","breakfast","kitchen","egg"],char:'🍳',fitzpatrick_scale:false,category:"food_and_drink"},hamburger:{keywords:["meat","fast food","beef","cheeseburger","mcdonalds","burger king"],char:'🍔',fitzpatrick_scale:false,category:"food_and_drink"},fries:{keywords:["chips","snack","fast food"],char:'🍟',fitzpatrick_scale:false,category:"food_and_drink"},stuffed_flatbread:{keywords:["food","flatbread","stuffed","gyro"],char:'🥙',fitzpatrick_scale:false,category:"food_and_drink"},hotdog:{keywords:["food","frankfurter"],char:'🌭',fitzpatrick_scale:false,category:"food_and_drink"},pizza:{keywords:["food","party"],char:'🍕',fitzpatrick_scale:false,category:"food_and_drink"},sandwich:{keywords:["food","lunch","bread"],char:'🥪',fitzpatrick_scale:false,category:"food_and_drink"},canned_food:{keywords:["food","soup"],char:'🥫',fitzpatrick_scale:false,category:"food_and_drink"},spaghetti:{keywords:["food","italian","noodle"],char:'🍝',fitzpatrick_scale:false,category:"food_and_drink"},taco:{keywords:["food","mexican"],char:'🌮',fitzpatrick_scale:false,category:"food_and_drink"},burrito:{keywords:["food","mexican"],char:'🌯',fitzpatrick_scale:false,category:"food_and_drink"},green_salad:{keywords:["food","healthy","lettuce"],char:'🥗',fitzpatrick_scale:false,category:"food_and_drink"},shallow_pan_of_food:{keywords:["food","cooking","casserole","paella"],char:'🥘',fitzpatrick_scale:false,category:"food_and_drink"},ramen:{keywords:["food","japanese","noodle","chopsticks"],char:'🍜',fitzpatrick_scale:false,category:"food_and_drink"},stew:{keywords:["food","meat","soup"],char:'🍲',fitzpatrick_scale:false,category:"food_and_drink"},fish_cake:{keywords:["food","japan","sea","beach","narutomaki","pink","swirl","kamaboko","surimi","ramen"],char:'🍥',fitzpatrick_scale:false,category:"food_and_drink"},fortune_cookie:{keywords:["food","prophecy"],char:'🥠',fitzpatrick_scale:false,category:"food_and_drink"},sushi:{keywords:["food","fish","japanese","rice"],char:'🍣',fitzpatrick_scale:false,category:"food_and_drink"},bento:{keywords:["food","japanese","box"],char:'🍱',fitzpatrick_scale:false,category:"food_and_drink"},curry:{keywords:["food","spicy","hot","indian"],char:'🍛',fitzpatrick_scale:false,category:"food_and_drink"},rice_ball:{keywords:["food","japanese"],char:'🍙',fitzpatrick_scale:false,category:"food_and_drink"},rice:{keywords:["food","china","asian"],char:'🍚',fitzpatrick_scale:false,category:"food_and_drink"},rice_cracker:{keywords:["food","japanese"],char:'🍘',fitzpatrick_scale:false,category:"food_and_drink"},oden:{keywords:["food","japanese"],char:'🍢',fitzpatrick_scale:false,category:"food_and_drink"},dango:{keywords:["food","dessert","sweet","japanese","barbecue","meat"],char:'🍡',fitzpatrick_scale:false,category:"food_and_drink"},shaved_ice:{keywords:["hot","dessert","summer"],char:'🍧',fitzpatrick_scale:false,category:"food_and_drink"},ice_cream:{keywords:["food","hot","dessert"],char:'🍨',fitzpatrick_scale:false,category:"food_and_drink"},icecream:{keywords:["food","hot","dessert","summer"],char:'🍦',fitzpatrick_scale:false,category:"food_and_drink"},pie:{keywords:["food","dessert","pastry"],char:'🥧',fitzpatrick_scale:false,category:"food_and_drink"},cake:{keywords:["food","dessert"],char:'🍰',fitzpatrick_scale:false,category:"food_and_drink"},cupcake:{keywords:["food","dessert","bakery","sweet"],char:'🧁',fitzpatrick_scale:false,category:"food_and_drink"},moon_cake:{keywords:["food","autumn"],char:'🥮',fitzpatrick_scale:false,category:"food_and_drink"},birthday:{keywords:["food","dessert","cake"],char:'🎂',fitzpatrick_scale:false,category:"food_and_drink"},custard:{keywords:["dessert","food"],char:'🍮',fitzpatrick_scale:false,category:"food_and_drink"},candy:{keywords:["snack","dessert","sweet","lolly"],char:'🍬',fitzpatrick_scale:false,category:"food_and_drink"},lollipop:{keywords:["food","snack","candy","sweet"],char:'🍭',fitzpatrick_scale:false,category:"food_and_drink"},chocolate_bar:{keywords:["food","snack","dessert","sweet"],char:'🍫',fitzpatrick_scale:false,category:"food_and_drink"},popcorn:{keywords:["food","movie theater","films","snack"],char:'🍿',fitzpatrick_scale:false,category:"food_and_drink"},dumpling:{keywords:["food","empanada","pierogi","potsticker"],char:'🥟',fitzpatrick_scale:false,category:"food_and_drink"},doughnut:{keywords:["food","dessert","snack","sweet","donut"],char:'🍩',fitzpatrick_scale:false,category:"food_and_drink"},cookie:{keywords:["food","snack","oreo","chocolate","sweet","dessert"],char:'🍪',fitzpatrick_scale:false,category:"food_and_drink"},milk_glass:{keywords:["beverage","drink","cow"],char:'🥛',fitzpatrick_scale:false,category:"food_and_drink"},beer:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:'🍺',fitzpatrick_scale:false,category:"food_and_drink"},beers:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:'🍻',fitzpatrick_scale:false,category:"food_and_drink"},clinking_glasses:{keywords:["beverage","drink","party","alcohol","celebrate","cheers","wine","champagne","toast"],char:'🥂',fitzpatrick_scale:false,category:"food_and_drink"},wine_glass:{keywords:["drink","beverage","drunk","alcohol","booze"],char:'🍷',fitzpatrick_scale:false,category:"food_and_drink"},tumbler_glass:{keywords:["drink","beverage","drunk","alcohol","liquor","booze","bourbon","scotch","whisky","glass","shot"],char:'🥃',fitzpatrick_scale:false,category:"food_and_drink"},cocktail:{keywords:["drink","drunk","alcohol","beverage","booze","mojito"],char:'🍸',fitzpatrick_scale:false,category:"food_and_drink"},tropical_drink:{keywords:["beverage","cocktail","summer","beach","alcohol","booze","mojito"],char:'🍹',fitzpatrick_scale:false,category:"food_and_drink"},champagne:{keywords:["drink","wine","bottle","celebration"],char:'🍾',fitzpatrick_scale:false,category:"food_and_drink"},sake:{keywords:["wine","drink","drunk","beverage","japanese","alcohol","booze"],char:'🍶',fitzpatrick_scale:false,category:"food_and_drink"},tea:{keywords:["drink","bowl","breakfast","green","british"],char:'🍵',fitzpatrick_scale:false,category:"food_and_drink"},cup_with_straw:{keywords:["drink","soda"],char:'🥤',fitzpatrick_scale:false,category:"food_and_drink"},coffee:{keywords:["beverage","caffeine","latte","espresso"],char:'☕',fitzpatrick_scale:false,category:"food_and_drink"},baby_bottle:{keywords:["food","container","milk"],char:'🍼',fitzpatrick_scale:false,category:"food_and_drink"},salt:{keywords:["condiment","shaker"],char:'🧂',fitzpatrick_scale:false,category:"food_and_drink"},spoon:{keywords:["cutlery","kitchen","tableware"],char:'🥄',fitzpatrick_scale:false,category:"food_and_drink"},fork_and_knife:{keywords:["cutlery","kitchen"],char:'🍴',fitzpatrick_scale:false,category:"food_and_drink"},plate_with_cutlery:{keywords:["food","eat","meal","lunch","dinner","restaurant"],char:'🍽',fitzpatrick_scale:false,category:"food_and_drink"},bowl_with_spoon:{keywords:["food","breakfast","cereal","oatmeal","porridge"],char:'🥣',fitzpatrick_scale:false,category:"food_and_drink"},takeout_box:{keywords:["food","leftovers"],char:'🥡',fitzpatrick_scale:false,category:"food_and_drink"},chopsticks:{keywords:["food"],char:'🥢',fitzpatrick_scale:false,category:"food_and_drink"},soccer:{keywords:["sports","football"],char:'⚽',fitzpatrick_scale:false,category:"activity"},basketball:{keywords:["sports","balls","NBA"],char:'🏀',fitzpatrick_scale:false,category:"activity"},football:{keywords:["sports","balls","NFL"],char:'🏈',fitzpatrick_scale:false,category:"activity"},baseball:{keywords:["sports","balls"],char:'⚾',fitzpatrick_scale:false,category:"activity"},softball:{keywords:["sports","balls"],char:'🥎',fitzpatrick_scale:false,category:"activity"},tennis:{keywords:["sports","balls","green"],char:'🎾',fitzpatrick_scale:false,category:"activity"},volleyball:{keywords:["sports","balls"],char:'🏐',fitzpatrick_scale:false,category:"activity"},rugby_football:{keywords:["sports","team"],char:'🏉',fitzpatrick_scale:false,category:"activity"},flying_disc:{keywords:["sports","frisbee","ultimate"],char:'🥏',fitzpatrick_scale:false,category:"activity"},"8ball":{keywords:["pool","hobby","game","luck","magic"],char:'🎱',fitzpatrick_scale:false,category:"activity"},golf:{keywords:["sports","business","flag","hole","summer"],char:'⛳',fitzpatrick_scale:false,category:"activity"},golfing_woman:{keywords:["sports","business","woman","female"],char:'🏌️‍♀️',fitzpatrick_scale:false,category:"activity"},golfing_man:{keywords:["sports","business"],char:'🏌',fitzpatrick_scale:true,category:"activity"},ping_pong:{keywords:["sports","pingpong"],char:'🏓',fitzpatrick_scale:false,category:"activity"},badminton:{keywords:["sports"],char:'🏸',fitzpatrick_scale:false,category:"activity"},goal_net:{keywords:["sports"],char:'🥅',fitzpatrick_scale:false,category:"activity"},ice_hockey:{keywords:["sports"],char:'🏒',fitzpatrick_scale:false,category:"activity"},field_hockey:{keywords:["sports"],char:'🏑',fitzpatrick_scale:false,category:"activity"},lacrosse:{keywords:["sports","ball","stick"],char:'🥍',fitzpatrick_scale:false,category:"activity"},cricket:{keywords:["sports"],char:'🏏',fitzpatrick_scale:false,category:"activity"},ski:{keywords:["sports","winter","cold","snow"],char:'🎿',fitzpatrick_scale:false,category:"activity"},skier:{keywords:["sports","winter","snow"],char:'⛷',fitzpatrick_scale:false,category:"activity"},snowboarder:{keywords:["sports","winter"],char:'🏂',fitzpatrick_scale:true,category:"activity"},person_fencing:{keywords:["sports","fencing","sword"],char:'🤺',fitzpatrick_scale:false,category:"activity"},women_wrestling:{keywords:["sports","wrestlers"],char:'🤼‍♀️',fitzpatrick_scale:false,category:"activity"},men_wrestling:{keywords:["sports","wrestlers"],char:'🤼‍♂️',fitzpatrick_scale:false,category:"activity"},woman_cartwheeling:{keywords:["gymnastics"],char:'🤸‍♀️',fitzpatrick_scale:true,category:"activity"},man_cartwheeling:{keywords:["gymnastics"],char:'🤸‍♂️',fitzpatrick_scale:true,category:"activity"},woman_playing_handball:{keywords:["sports"],char:'🤾‍♀️',fitzpatrick_scale:true,category:"activity"},man_playing_handball:{keywords:["sports"],char:'🤾‍♂️',fitzpatrick_scale:true,category:"activity"},ice_skate:{keywords:["sports"],char:'⛸',fitzpatrick_scale:false,category:"activity"},curling_stone:{keywords:["sports"],char:'🥌',fitzpatrick_scale:false,category:"activity"},skateboard:{keywords:["board"],char:'🛹',fitzpatrick_scale:false,category:"activity"},sled:{keywords:["sleigh","luge","toboggan"],char:'🛷',fitzpatrick_scale:false,category:"activity"},bow_and_arrow:{keywords:["sports"],char:'🏹',fitzpatrick_scale:false,category:"activity"},fishing_pole_and_fish:{keywords:["food","hobby","summer"],char:'🎣',fitzpatrick_scale:false,category:"activity"},boxing_glove:{keywords:["sports","fighting"],char:'🥊',fitzpatrick_scale:false,category:"activity"},martial_arts_uniform:{keywords:["judo","karate","taekwondo"],char:'🥋',fitzpatrick_scale:false,category:"activity"},rowing_woman:{keywords:["sports","hobby","water","ship","woman","female"],char:'🚣‍♀️',fitzpatrick_scale:true,category:"activity"},rowing_man:{keywords:["sports","hobby","water","ship"],char:'🚣',fitzpatrick_scale:true,category:"activity"},climbing_woman:{keywords:["sports","hobby","woman","female","rock"],char:'🧗‍♀️',fitzpatrick_scale:true,category:"activity"},climbing_man:{keywords:["sports","hobby","man","male","rock"],char:'🧗‍♂️',fitzpatrick_scale:true,category:"activity"},swimming_woman:{keywords:["sports","exercise","human","athlete","water","summer","woman","female"],char:'🏊‍♀️',fitzpatrick_scale:true,category:"activity"},swimming_man:{keywords:["sports","exercise","human","athlete","water","summer"],char:'🏊',fitzpatrick_scale:true,category:"activity"},woman_playing_water_polo:{keywords:["sports","pool"],char:'🤽‍♀️',fitzpatrick_scale:true,category:"activity"},man_playing_water_polo:{keywords:["sports","pool"],char:'🤽‍♂️',fitzpatrick_scale:true,category:"activity"},woman_in_lotus_position:{keywords:["woman","female","meditation","yoga","serenity","zen","mindfulness"],char:'🧘‍♀️',fitzpatrick_scale:true,category:"activity"},man_in_lotus_position:{keywords:["man","male","meditation","yoga","serenity","zen","mindfulness"],char:'🧘‍♂️',fitzpatrick_scale:true,category:"activity"},surfing_woman:{keywords:["sports","ocean","sea","summer","beach","woman","female"],char:'🏄‍♀️',fitzpatrick_scale:true,category:"activity"},surfing_man:{keywords:["sports","ocean","sea","summer","beach"],char:'🏄',fitzpatrick_scale:true,category:"activity"},bath:{keywords:["clean","shower","bathroom"],char:'🛀',fitzpatrick_scale:true,category:"activity"},basketball_woman:{keywords:["sports","human","woman","female"],char:'⛹️‍♀️',fitzpatrick_scale:true,category:"activity"},basketball_man:{keywords:["sports","human"],char:'⛹',fitzpatrick_scale:true,category:"activity"},weight_lifting_woman:{keywords:["sports","training","exercise","woman","female"],char:'🏋️‍♀️',fitzpatrick_scale:true,category:"activity"},weight_lifting_man:{keywords:["sports","training","exercise"],char:'🏋',fitzpatrick_scale:true,category:"activity"},biking_woman:{keywords:["sports","bike","exercise","hipster","woman","female"],char:'🚴‍♀️',fitzpatrick_scale:true,category:"activity"},biking_man:{keywords:["sports","bike","exercise","hipster"],char:'🚴',fitzpatrick_scale:true,category:"activity"},mountain_biking_woman:{keywords:["transportation","sports","human","race","bike","woman","female"],char:'🚵‍♀️',fitzpatrick_scale:true,category:"activity"},mountain_biking_man:{keywords:["transportation","sports","human","race","bike"],char:'🚵',fitzpatrick_scale:true,category:"activity"},horse_racing:{keywords:["animal","betting","competition","gambling","luck"],char:'🏇',fitzpatrick_scale:true,category:"activity"},business_suit_levitating:{keywords:["suit","business","levitate","hover","jump"],char:'🕴',fitzpatrick_scale:true,category:"activity"},trophy:{keywords:["win","award","contest","place","ftw","ceremony"],char:'🏆',fitzpatrick_scale:false,category:"activity"},running_shirt_with_sash:{keywords:["play","pageant"],char:'🎽',fitzpatrick_scale:false,category:"activity"},medal_sports:{keywords:["award","winning"],char:'🏅',fitzpatrick_scale:false,category:"activity"},medal_military:{keywords:["award","winning","army"],char:'🎖',fitzpatrick_scale:false,category:"activity"},"1st_place_medal":{keywords:["award","winning","first"],char:'🥇',fitzpatrick_scale:false,category:"activity"},"2nd_place_medal":{keywords:["award","second"],char:'🥈',fitzpatrick_scale:false,category:"activity"},"3rd_place_medal":{keywords:["award","third"],char:'🥉',fitzpatrick_scale:false,category:"activity"},reminder_ribbon:{keywords:["sports","cause","support","awareness"],char:'🎗',fitzpatrick_scale:false,category:"activity"},rosette:{keywords:["flower","decoration","military"],char:'🏵',fitzpatrick_scale:false,category:"activity"},ticket:{keywords:["event","concert","pass"],char:'🎫',fitzpatrick_scale:false,category:"activity"},tickets:{keywords:["sports","concert","entrance"],char:'🎟',fitzpatrick_scale:false,category:"activity"},performing_arts:{keywords:["acting","theater","drama"],char:'🎭',fitzpatrick_scale:false,category:"activity"},art:{keywords:["design","paint","draw","colors"],char:'🎨',fitzpatrick_scale:false,category:"activity"},circus_tent:{keywords:["festival","carnival","party"],char:'🎪',fitzpatrick_scale:false,category:"activity"},woman_juggling:{keywords:["juggle","balance","skill","multitask"],char:'🤹‍♀️',fitzpatrick_scale:true,category:"activity"},man_juggling:{keywords:["juggle","balance","skill","multitask"],char:'🤹‍♂️',fitzpatrick_scale:true,category:"activity"},microphone:{keywords:["sound","music","PA","sing","talkshow"],char:'🎤',fitzpatrick_scale:false,category:"activity"},headphones:{keywords:["music","score","gadgets"],char:'🎧',fitzpatrick_scale:false,category:"activity"},musical_score:{keywords:["treble","clef","compose"],char:'🎼',fitzpatrick_scale:false,category:"activity"},musical_keyboard:{keywords:["piano","instrument","compose"],char:'🎹',fitzpatrick_scale:false,category:"activity"},drum:{keywords:["music","instrument","drumsticks","snare"],char:'🥁',fitzpatrick_scale:false,category:"activity"},saxophone:{keywords:["music","instrument","jazz","blues"],char:'🎷',fitzpatrick_scale:false,category:"activity"},trumpet:{keywords:["music","brass"],char:'🎺',fitzpatrick_scale:false,category:"activity"},guitar:{keywords:["music","instrument"],char:'🎸',fitzpatrick_scale:false,category:"activity"},violin:{keywords:["music","instrument","orchestra","symphony"],char:'🎻',fitzpatrick_scale:false,category:"activity"},clapper:{keywords:["movie","film","record"],char:'🎬',fitzpatrick_scale:false,category:"activity"},video_game:{keywords:["play","console","PS4","controller"],char:'🎮',fitzpatrick_scale:false,category:"activity"},space_invader:{keywords:["game","arcade","play"],char:'👾',fitzpatrick_scale:false,category:"activity"},dart:{keywords:["game","play","bar","target","bullseye"],char:'🎯',fitzpatrick_scale:false,category:"activity"},game_die:{keywords:["dice","random","tabletop","play","luck"],char:'🎲',fitzpatrick_scale:false,category:"activity"},chess_pawn:{keywords:["expendable"],char:"♟",fitzpatrick_scale:false,category:"activity"},slot_machine:{keywords:["bet","gamble","vegas","fruit machine","luck","casino"],char:'🎰',fitzpatrick_scale:false,category:"activity"},jigsaw:{keywords:["interlocking","puzzle","piece"],char:'🧩',fitzpatrick_scale:false,category:"activity"},bowling:{keywords:["sports","fun","play"],char:'🎳',fitzpatrick_scale:false,category:"activity"},red_car:{keywords:["red","transportation","vehicle"],char:'🚗',fitzpatrick_scale:false,category:"travel_and_places"},taxi:{keywords:["uber","vehicle","cars","transportation"],char:'🚕',fitzpatrick_scale:false,category:"travel_and_places"},blue_car:{keywords:["transportation","vehicle"],char:'🚙',fitzpatrick_scale:false,category:"travel_and_places"},bus:{keywords:["car","vehicle","transportation"],char:'🚌',fitzpatrick_scale:false,category:"travel_and_places"},trolleybus:{keywords:["bart","transportation","vehicle"],char:'🚎',fitzpatrick_scale:false,category:"travel_and_places"},racing_car:{keywords:["sports","race","fast","formula","f1"],char:'🏎',fitzpatrick_scale:false,category:"travel_and_places"},police_car:{keywords:["vehicle","cars","transportation","law","legal","enforcement"],char:'🚓',fitzpatrick_scale:false,category:"travel_and_places"},ambulance:{keywords:["health","911","hospital"],char:'🚑',fitzpatrick_scale:false,category:"travel_and_places"},fire_engine:{keywords:["transportation","cars","vehicle"],char:'🚒',fitzpatrick_scale:false,category:"travel_and_places"},minibus:{keywords:["vehicle","car","transportation"],char:'🚐',fitzpatrick_scale:false,category:"travel_and_places"},truck:{keywords:["cars","transportation"],char:'🚚',fitzpatrick_scale:false,category:"travel_and_places"},articulated_lorry:{keywords:["vehicle","cars","transportation","express"],char:'🚛',fitzpatrick_scale:false,category:"travel_and_places"},tractor:{keywords:["vehicle","car","farming","agriculture"],char:'🚜',fitzpatrick_scale:false,category:"travel_and_places"},kick_scooter:{keywords:["vehicle","kick","razor"],char:'🛴',fitzpatrick_scale:false,category:"travel_and_places"},motorcycle:{keywords:["race","sports","fast"],char:'🏍',fitzpatrick_scale:false,category:"travel_and_places"},bike:{keywords:["sports","bicycle","exercise","hipster"],char:'🚲',fitzpatrick_scale:false,category:"travel_and_places"},motor_scooter:{keywords:["vehicle","vespa","sasha"],char:'🛵',fitzpatrick_scale:false,category:"travel_and_places"},rotating_light:{keywords:["police","ambulance","911","emergency","alert","error","pinged","law","legal"],char:'🚨',fitzpatrick_scale:false,category:"travel_and_places"},oncoming_police_car:{keywords:["vehicle","law","legal","enforcement","911"],char:'🚔',fitzpatrick_scale:false,category:"travel_and_places"},oncoming_bus:{keywords:["vehicle","transportation"],char:'🚍',fitzpatrick_scale:false,category:"travel_and_places"},oncoming_automobile:{keywords:["car","vehicle","transportation"],char:'🚘',fitzpatrick_scale:false,category:"travel_and_places"},oncoming_taxi:{keywords:["vehicle","cars","uber"],char:'🚖',fitzpatrick_scale:false,category:"travel_and_places"},aerial_tramway:{keywords:["transportation","vehicle","ski"],char:'🚡',fitzpatrick_scale:false,category:"travel_and_places"},mountain_cableway:{keywords:["transportation","vehicle","ski"],char:'🚠',fitzpatrick_scale:false,category:"travel_and_places"},suspension_railway:{keywords:["vehicle","transportation"],char:'🚟',fitzpatrick_scale:false,category:"travel_and_places"},railway_car:{keywords:["transportation","vehicle"],char:'🚃',fitzpatrick_scale:false,category:"travel_and_places"},train:{keywords:["transportation","vehicle","carriage","public","travel"],char:'🚋',fitzpatrick_scale:false,category:"travel_and_places"},monorail:{keywords:["transportation","vehicle"],char:'🚝',fitzpatrick_scale:false,category:"travel_and_places"},bullettrain_side:{keywords:["transportation","vehicle"],char:'🚄',fitzpatrick_scale:false,category:"travel_and_places"},bullettrain_front:{keywords:["transportation","vehicle","speed","fast","public","travel"],char:'🚅',fitzpatrick_scale:false,category:"travel_and_places"},light_rail:{keywords:["transportation","vehicle"],char:'🚈',fitzpatrick_scale:false,category:"travel_and_places"},mountain_railway:{keywords:["transportation","vehicle"],char:'🚞',fitzpatrick_scale:false,category:"travel_and_places"},steam_locomotive:{keywords:["transportation","vehicle","train"],char:'🚂',fitzpatrick_scale:false,category:"travel_and_places"},train2:{keywords:["transportation","vehicle"],char:'🚆',fitzpatrick_scale:false,category:"travel_and_places"},metro:{keywords:["transportation","blue-square","mrt","underground","tube"],char:'🚇',fitzpatrick_scale:false,category:"travel_and_places"},tram:{keywords:["transportation","vehicle"],char:'🚊',fitzpatrick_scale:false,category:"travel_and_places"},station:{keywords:["transportation","vehicle","public"],char:'🚉',fitzpatrick_scale:false,category:"travel_and_places"},flying_saucer:{keywords:["transportation","vehicle","ufo"],char:'🛸',fitzpatrick_scale:false,category:"travel_and_places"},helicopter:{keywords:["transportation","vehicle","fly"],char:'🚁',fitzpatrick_scale:false,category:"travel_and_places"},small_airplane:{keywords:["flight","transportation","fly","vehicle"],char:'🛩',fitzpatrick_scale:false,category:"travel_and_places"},airplane:{keywords:["vehicle","transportation","flight","fly"],char:'✈️',fitzpatrick_scale:false,category:"travel_and_places"},flight_departure:{keywords:["airport","flight","landing"],char:'🛫',fitzpatrick_scale:false,category:"travel_and_places"},flight_arrival:{keywords:["airport","flight","boarding"],char:'🛬',fitzpatrick_scale:false,category:"travel_and_places"},sailboat:{keywords:["ship","summer","transportation","water","sailing"],char:'⛵',fitzpatrick_scale:false,category:"travel_and_places"},motor_boat:{keywords:["ship"],char:'🛥',fitzpatrick_scale:false,category:"travel_and_places"},speedboat:{keywords:["ship","transportation","vehicle","summer"],char:'🚤',fitzpatrick_scale:false,category:"travel_and_places"},ferry:{keywords:["boat","ship","yacht"],char:'⛴',fitzpatrick_scale:false,category:"travel_and_places"},passenger_ship:{keywords:["yacht","cruise","ferry"],char:'🛳',fitzpatrick_scale:false,category:"travel_and_places"},rocket:{keywords:["launch","ship","staffmode","NASA","outer space","outer_space","fly"],char:'🚀',fitzpatrick_scale:false,category:"travel_and_places"},artificial_satellite:{keywords:["communication","gps","orbit","spaceflight","NASA","ISS"],char:'🛰',fitzpatrick_scale:false,category:"travel_and_places"},seat:{keywords:["sit","airplane","transport","bus","flight","fly"],char:'💺',fitzpatrick_scale:false,category:"travel_and_places"},canoe:{keywords:["boat","paddle","water","ship"],char:'🛶',fitzpatrick_scale:false,category:"travel_and_places"},anchor:{keywords:["ship","ferry","sea","boat"],char:'⚓',fitzpatrick_scale:false,category:"travel_and_places"},construction:{keywords:["wip","progress","caution","warning"],char:'🚧',fitzpatrick_scale:false,category:"travel_and_places"},fuelpump:{keywords:["gas station","petroleum"],char:'⛽',fitzpatrick_scale:false,category:"travel_and_places"},busstop:{keywords:["transportation","wait"],char:'🚏',fitzpatrick_scale:false,category:"travel_and_places"},vertical_traffic_light:{keywords:["transportation","driving"],char:'🚦',fitzpatrick_scale:false,category:"travel_and_places"},traffic_light:{keywords:["transportation","signal"],char:'🚥',fitzpatrick_scale:false,category:"travel_and_places"},checkered_flag:{keywords:["contest","finishline","race","gokart"],char:'🏁',fitzpatrick_scale:false,category:"travel_and_places"},ship:{keywords:["transportation","titanic","deploy"],char:'🚢',fitzpatrick_scale:false,category:"travel_and_places"},ferris_wheel:{keywords:["photo","carnival","londoneye"],char:'🎡',fitzpatrick_scale:false,category:"travel_and_places"},roller_coaster:{keywords:["carnival","playground","photo","fun"],char:'🎢',fitzpatrick_scale:false,category:"travel_and_places"},carousel_horse:{keywords:["photo","carnival"],char:'🎠',fitzpatrick_scale:false,category:"travel_and_places"},building_construction:{keywords:["wip","working","progress"],char:'🏗',fitzpatrick_scale:false,category:"travel_and_places"},foggy:{keywords:["photo","mountain"],char:'🌁',fitzpatrick_scale:false,category:"travel_and_places"},tokyo_tower:{keywords:["photo","japanese"],char:'🗼',fitzpatrick_scale:false,category:"travel_and_places"},factory:{keywords:["building","industry","pollution","smoke"],char:'🏭',fitzpatrick_scale:false,category:"travel_and_places"},fountain:{keywords:["photo","summer","water","fresh"],char:'⛲',fitzpatrick_scale:false,category:"travel_and_places"},rice_scene:{keywords:["photo","japan","asia","tsukimi"],char:'🎑',fitzpatrick_scale:false,category:"travel_and_places"},mountain:{keywords:["photo","nature","environment"],char:'⛰',fitzpatrick_scale:false,category:"travel_and_places"},mountain_snow:{keywords:["photo","nature","environment","winter","cold"],char:'🏔',fitzpatrick_scale:false,category:"travel_and_places"},mount_fuji:{keywords:["photo","mountain","nature","japanese"],char:'🗻',fitzpatrick_scale:false,category:"travel_and_places"},volcano:{keywords:["photo","nature","disaster"],char:'🌋',fitzpatrick_scale:false,category:"travel_and_places"},japan:{keywords:["nation","country","japanese","asia"],char:'🗾',fitzpatrick_scale:false,category:"travel_and_places"},camping:{keywords:["photo","outdoors","tent"],char:'🏕',fitzpatrick_scale:false,category:"travel_and_places"},tent:{keywords:["photo","camping","outdoors"],char:'⛺',fitzpatrick_scale:false,category:"travel_and_places"},national_park:{keywords:["photo","environment","nature"],char:'🏞',fitzpatrick_scale:false,category:"travel_and_places"},motorway:{keywords:["road","cupertino","interstate","highway"],char:'🛣',fitzpatrick_scale:false,category:"travel_and_places"},railway_track:{keywords:["train","transportation"],char:'🛤',fitzpatrick_scale:false,category:"travel_and_places"},sunrise:{keywords:["morning","view","vacation","photo"],char:'🌅',fitzpatrick_scale:false,category:"travel_and_places"},sunrise_over_mountains:{keywords:["view","vacation","photo"],char:'🌄',fitzpatrick_scale:false,category:"travel_and_places"},desert:{keywords:["photo","warm","saharah"],char:'🏜',fitzpatrick_scale:false,category:"travel_and_places"},beach_umbrella:{keywords:["weather","summer","sunny","sand","mojito"],char:'🏖',fitzpatrick_scale:false,category:"travel_and_places"},desert_island:{keywords:["photo","tropical","mojito"],char:'🏝',fitzpatrick_scale:false,category:"travel_and_places"},city_sunrise:{keywords:["photo","good morning","dawn"],char:'🌇',fitzpatrick_scale:false,category:"travel_and_places"},city_sunset:{keywords:["photo","evening","sky","buildings"],char:'🌆',fitzpatrick_scale:false,category:"travel_and_places"},cityscape:{keywords:["photo","night life","urban"],char:'🏙',fitzpatrick_scale:false,category:"travel_and_places"},night_with_stars:{keywords:["evening","city","downtown"],char:'🌃',fitzpatrick_scale:false,category:"travel_and_places"},bridge_at_night:{keywords:["photo","sanfrancisco"],char:'🌉',fitzpatrick_scale:false,category:"travel_and_places"},milky_way:{keywords:["photo","space","stars"],char:'🌌',fitzpatrick_scale:false,category:"travel_and_places"},stars:{keywords:["night","photo"],char:'🌠',fitzpatrick_scale:false,category:"travel_and_places"},sparkler:{keywords:["stars","night","shine"],char:'🎇',fitzpatrick_scale:false,category:"travel_and_places"},fireworks:{keywords:["photo","festival","carnival","congratulations"],char:'🎆',fitzpatrick_scale:false,category:"travel_and_places"},rainbow:{keywords:["nature","happy","unicorn_face","photo","sky","spring"],char:'🌈',fitzpatrick_scale:false,category:"travel_and_places"},houses:{keywords:["buildings","photo"],char:'🏘',fitzpatrick_scale:false,category:"travel_and_places"},european_castle:{keywords:["building","royalty","history"],char:'🏰',fitzpatrick_scale:false,category:"travel_and_places"},japanese_castle:{keywords:["photo","building"],char:'🏯',fitzpatrick_scale:false,category:"travel_and_places"},stadium:{keywords:["photo","place","sports","concert","venue"],char:'🏟',fitzpatrick_scale:false,category:"travel_and_places"},statue_of_liberty:{keywords:["american","newyork"],char:'🗽',fitzpatrick_scale:false,category:"travel_and_places"},house:{keywords:["building","home"],char:'🏠',fitzpatrick_scale:false,category:"travel_and_places"},house_with_garden:{keywords:["home","plant","nature"],char:'🏡',fitzpatrick_scale:false,category:"travel_and_places"},derelict_house:{keywords:["abandon","evict","broken","building"],char:'🏚',fitzpatrick_scale:false,category:"travel_and_places"},office:{keywords:["building","bureau","work"],char:'🏢',fitzpatrick_scale:false,category:"travel_and_places"},department_store:{keywords:["building","shopping","mall"],char:'🏬',fitzpatrick_scale:false,category:"travel_and_places"},post_office:{keywords:["building","envelope","communication"],char:'🏣',fitzpatrick_scale:false,category:"travel_and_places"},european_post_office:{keywords:["building","email"],char:'🏤',fitzpatrick_scale:false,category:"travel_and_places"},hospital:{keywords:["building","health","surgery","doctor"],char:'🏥',fitzpatrick_scale:false,category:"travel_and_places"},bank:{keywords:["building","money","sales","cash","business","enterprise"],char:'🏦',fitzpatrick_scale:false,category:"travel_and_places"},hotel:{keywords:["building","accomodation","checkin"],char:'🏨',fitzpatrick_scale:false,category:"travel_and_places"},convenience_store:{keywords:["building","shopping","groceries"],char:'🏪',fitzpatrick_scale:false,category:"travel_and_places"},school:{keywords:["building","student","education","learn","teach"],char:'🏫',fitzpatrick_scale:false,category:"travel_and_places"},love_hotel:{keywords:["like","affection","dating"],char:'🏩',fitzpatrick_scale:false,category:"travel_and_places"},wedding:{keywords:["love","like","affection","couple","marriage","bride","groom"],char:'💒',fitzpatrick_scale:false,category:"travel_and_places"},classical_building:{keywords:["art","culture","history"],char:'🏛',fitzpatrick_scale:false,category:"travel_and_places"},church:{keywords:["building","religion","christ"],char:'⛪',fitzpatrick_scale:false,category:"travel_and_places"},mosque:{keywords:["islam","worship","minaret"],char:'🕌',fitzpatrick_scale:false,category:"travel_and_places"},synagogue:{keywords:["judaism","worship","temple","jewish"],char:'🕍',fitzpatrick_scale:false,category:"travel_and_places"},kaaba:{keywords:["mecca","mosque","islam"],char:'🕋',fitzpatrick_scale:false,category:"travel_and_places"},shinto_shrine:{keywords:["temple","japan","kyoto"],char:'⛩',fitzpatrick_scale:false,category:"travel_and_places"},watch:{keywords:["time","accessories"],char:'⌚',fitzpatrick_scale:false,category:"objects"},iphone:{keywords:["technology","apple","gadgets","dial"],char:'📱',fitzpatrick_scale:false,category:"objects"},calling:{keywords:["iphone","incoming"],char:'📲',fitzpatrick_scale:false,category:"objects"},computer:{keywords:["technology","laptop","screen","display","monitor"],char:'💻',fitzpatrick_scale:false,category:"objects"},keyboard:{keywords:["technology","computer","type","input","text"],char:'⌨',fitzpatrick_scale:false,category:"objects"},desktop_computer:{keywords:["technology","computing","screen"],char:'🖥',fitzpatrick_scale:false,category:"objects"},printer:{keywords:["paper","ink"],char:'🖨',fitzpatrick_scale:false,category:"objects"},computer_mouse:{keywords:["click"],char:'🖱',fitzpatrick_scale:false,category:"objects"},trackball:{keywords:["technology","trackpad"],char:'🖲',fitzpatrick_scale:false,category:"objects"},joystick:{keywords:["game","play"],char:'🕹',fitzpatrick_scale:false,category:"objects"},clamp:{keywords:["tool"],char:'🗜',fitzpatrick_scale:false,category:"objects"},minidisc:{keywords:["technology","record","data","disk","90s"],char:'💽',fitzpatrick_scale:false,category:"objects"},floppy_disk:{keywords:["oldschool","technology","save","90s","80s"],char:'💾',fitzpatrick_scale:false,category:"objects"},cd:{keywords:["technology","dvd","disk","disc","90s"],char:'💿',fitzpatrick_scale:false,category:"objects"},dvd:{keywords:["cd","disk","disc"],char:'📀',fitzpatrick_scale:false,category:"objects"},vhs:{keywords:["record","video","oldschool","90s","80s"],char:'📼',fitzpatrick_scale:false,category:"objects"},camera:{keywords:["gadgets","photography"],char:'📷',fitzpatrick_scale:false,category:"objects"},camera_flash:{keywords:["photography","gadgets"],char:'📸',fitzpatrick_scale:false,category:"objects"},video_camera:{keywords:["film","record"],char:'📹',fitzpatrick_scale:false,category:"objects"},movie_camera:{keywords:["film","record"],char:'🎥',fitzpatrick_scale:false,category:"objects"},film_projector:{keywords:["video","tape","record","movie"],char:'📽',fitzpatrick_scale:false,category:"objects"},film_strip:{keywords:["movie"],char:'🎞',fitzpatrick_scale:false,category:"objects"},telephone_receiver:{keywords:["technology","communication","dial"],char:'📞',fitzpatrick_scale:false,category:"objects"},phone:{keywords:["technology","communication","dial","telephone"],char:'☎️',fitzpatrick_scale:false,category:"objects"},pager:{keywords:["bbcall","oldschool","90s"],char:'📟',fitzpatrick_scale:false,category:"objects"},fax:{keywords:["communication","technology"],char:'📠',fitzpatrick_scale:false,category:"objects"},tv:{keywords:["technology","program","oldschool","show","television"],char:'📺',fitzpatrick_scale:false,category:"objects"},radio:{keywords:["communication","music","podcast","program"],char:'📻',fitzpatrick_scale:false,category:"objects"},studio_microphone:{keywords:["sing","recording","artist","talkshow"],char:'🎙',fitzpatrick_scale:false,category:"objects"},level_slider:{keywords:["scale"],char:'🎚',fitzpatrick_scale:false,category:"objects"},control_knobs:{keywords:["dial"],char:'🎛',fitzpatrick_scale:false,category:"objects"},compass:{keywords:["magnetic","navigation","orienteering"],char:'🧭',fitzpatrick_scale:false,category:"objects"},stopwatch:{keywords:["time","deadline"],char:'⏱',fitzpatrick_scale:false,category:"objects"},timer_clock:{keywords:["alarm"],char:'⏲',fitzpatrick_scale:false,category:"objects"},alarm_clock:{keywords:["time","wake"],char:'⏰',fitzpatrick_scale:false,category:"objects"},mantelpiece_clock:{keywords:["time"],char:'🕰',fitzpatrick_scale:false,category:"objects"},hourglass_flowing_sand:{keywords:["oldschool","time","countdown"],char:'⏳',fitzpatrick_scale:false,category:"objects"},hourglass:{keywords:["time","clock","oldschool","limit","exam","quiz","test"],char:'⌛',fitzpatrick_scale:false,category:"objects"},satellite:{keywords:["communication","future","radio","space"],char:'📡',fitzpatrick_scale:false,category:"objects"},battery:{keywords:["power","energy","sustain"],char:'🔋',fitzpatrick_scale:false,category:"objects"},electric_plug:{keywords:["charger","power"],char:'🔌',fitzpatrick_scale:false,category:"objects"},bulb:{keywords:["light","electricity","idea"],char:'💡',fitzpatrick_scale:false,category:"objects"},flashlight:{keywords:["dark","camping","sight","night"],char:'🔦',fitzpatrick_scale:false,category:"objects"},candle:{keywords:["fire","wax"],char:'🕯',fitzpatrick_scale:false,category:"objects"},fire_extinguisher:{keywords:["quench"],char:'🧯',fitzpatrick_scale:false,category:"objects"},wastebasket:{keywords:["bin","trash","rubbish","garbage","toss"],char:'🗑',fitzpatrick_scale:false,category:"objects"},oil_drum:{keywords:["barrell"],char:'🛢',fitzpatrick_scale:false,category:"objects"},money_with_wings:{keywords:["dollar","bills","payment","sale"],char:'💸',fitzpatrick_scale:false,category:"objects"},dollar:{keywords:["money","sales","bill","currency"],char:'💵',fitzpatrick_scale:false,category:"objects"},yen:{keywords:["money","sales","japanese","dollar","currency"],char:'💴',fitzpatrick_scale:false,category:"objects"},euro:{keywords:["money","sales","dollar","currency"],char:'💶',fitzpatrick_scale:false,category:"objects"},pound:{keywords:["british","sterling","money","sales","bills","uk","england","currency"],char:'💷',fitzpatrick_scale:false,category:"objects"},moneybag:{keywords:["dollar","payment","coins","sale"],char:'💰',fitzpatrick_scale:false,category:"objects"},credit_card:{keywords:["money","sales","dollar","bill","payment","shopping"],char:'💳',fitzpatrick_scale:false,category:"objects"},gem:{keywords:["blue","ruby","diamond","jewelry"],char:'💎',fitzpatrick_scale:false,category:"objects"},balance_scale:{keywords:["law","fairness","weight"],char:'⚖',fitzpatrick_scale:false,category:"objects"},toolbox:{keywords:["tools","diy","fix","maintainer","mechanic"],char:'🧰',fitzpatrick_scale:false,category:"objects"},wrench:{keywords:["tools","diy","ikea","fix","maintainer"],char:'🔧',fitzpatrick_scale:false,category:"objects"},hammer:{keywords:["tools","build","create"],char:'🔨',fitzpatrick_scale:false,category:"objects"},hammer_and_pick:{keywords:["tools","build","create"],char:'⚒',fitzpatrick_scale:false,category:"objects"},hammer_and_wrench:{keywords:["tools","build","create"],char:'🛠',fitzpatrick_scale:false,category:"objects"},pick:{keywords:["tools","dig"],char:'⛏',fitzpatrick_scale:false,category:"objects"},nut_and_bolt:{keywords:["handy","tools","fix"],char:'🔩',fitzpatrick_scale:false,category:"objects"},gear:{keywords:["cog"],char:'⚙',fitzpatrick_scale:false,category:"objects"},brick:{keywords:["bricks"],char:'🧱',fitzpatrick_scale:false,category:"objects"},chains:{keywords:["lock","arrest"],char:'⛓',fitzpatrick_scale:false,category:"objects"},magnet:{keywords:["attraction","magnetic"],char:'🧲',fitzpatrick_scale:false,category:"objects"},gun:{keywords:["violence","weapon","pistol","revolver"],char:'🔫',fitzpatrick_scale:false,category:"objects"},bomb:{keywords:["boom","explode","explosion","terrorism"],char:'💣',fitzpatrick_scale:false,category:"objects"},firecracker:{keywords:["dynamite","boom","explode","explosion","explosive"],char:'🧨',fitzpatrick_scale:false,category:"objects"},hocho:{keywords:["knife","blade","cutlery","kitchen","weapon"],char:'🔪',fitzpatrick_scale:false,category:"objects"},dagger:{keywords:["weapon"],char:'🗡',fitzpatrick_scale:false,category:"objects"},crossed_swords:{keywords:["weapon"],char:'⚔',fitzpatrick_scale:false,category:"objects"},shield:{keywords:["protection","security"],char:'🛡',fitzpatrick_scale:false,category:"objects"},smoking:{keywords:["kills","tobacco","cigarette","joint","smoke"],char:'🚬',fitzpatrick_scale:false,category:"objects"},skull_and_crossbones:{keywords:["poison","danger","deadly","scary","death","pirate","evil"],char:'☠',fitzpatrick_scale:false,category:"objects"},coffin:{keywords:["vampire","dead","die","death","rip","graveyard","cemetery","casket","funeral","box"],char:'⚰',fitzpatrick_scale:false,category:"objects"},funeral_urn:{keywords:["dead","die","death","rip","ashes"],char:'⚱',fitzpatrick_scale:false,category:"objects"},amphora:{keywords:["vase","jar"],char:'🏺',fitzpatrick_scale:false,category:"objects"},crystal_ball:{keywords:["disco","party","magic","circus","fortune_teller"],char:'🔮',fitzpatrick_scale:false,category:"objects"},prayer_beads:{keywords:["dhikr","religious"],char:'📿',fitzpatrick_scale:false,category:"objects"},nazar_amulet:{keywords:["bead","charm"],char:'🧿',fitzpatrick_scale:false,category:"objects"},barber:{keywords:["hair","salon","style"],char:'💈',fitzpatrick_scale:false,category:"objects"},alembic:{keywords:["distilling","science","experiment","chemistry"],char:'⚗',fitzpatrick_scale:false,category:"objects"},telescope:{keywords:["stars","space","zoom","science","astronomy"],char:'🔭',fitzpatrick_scale:false,category:"objects"},microscope:{keywords:["laboratory","experiment","zoomin","science","study"],char:'🔬',fitzpatrick_scale:false,category:"objects"},hole:{keywords:["embarrassing"],char:'🕳',fitzpatrick_scale:false,category:"objects"},pill:{keywords:["health","medicine","doctor","pharmacy","drug"],char:'💊',fitzpatrick_scale:false,category:"objects"},syringe:{keywords:["health","hospital","drugs","blood","medicine","needle","doctor","nurse"],char:'💉',fitzpatrick_scale:false,category:"objects"},dna:{keywords:["biologist","genetics","life"],char:'🧬',fitzpatrick_scale:false,category:"objects"},microbe:{keywords:["amoeba","bacteria","germs"],char:'🦠',fitzpatrick_scale:false,category:"objects"},petri_dish:{keywords:["bacteria","biology","culture","lab"],char:'🧫',fitzpatrick_scale:false,category:"objects"},test_tube:{keywords:["chemistry","experiment","lab","science"],char:'🧪',fitzpatrick_scale:false,category:"objects"},thermometer:{keywords:["weather","temperature","hot","cold"],char:'🌡',fitzpatrick_scale:false,category:"objects"},broom:{keywords:["cleaning","sweeping","witch"],char:'🧹',fitzpatrick_scale:false,category:"objects"},basket:{keywords:["laundry"],char:'🧺',fitzpatrick_scale:false,category:"objects"},toilet_paper:{keywords:["roll"],char:'🧻',fitzpatrick_scale:false,category:"objects"},label:{keywords:["sale","tag"],char:'🏷',fitzpatrick_scale:false,category:"objects"},bookmark:{keywords:["favorite","label","save"],char:'🔖',fitzpatrick_scale:false,category:"objects"},toilet:{keywords:["restroom","wc","washroom","bathroom","potty"],char:'🚽',fitzpatrick_scale:false,category:"objects"},shower:{keywords:["clean","water","bathroom"],char:'🚿',fitzpatrick_scale:false,category:"objects"},bathtub:{keywords:["clean","shower","bathroom"],char:'🛁',fitzpatrick_scale:false,category:"objects"},soap:{keywords:["bar","bathing","cleaning","lather"],char:'🧼',fitzpatrick_scale:false,category:"objects"},sponge:{keywords:["absorbing","cleaning","porous"],char:'🧽',fitzpatrick_scale:false,category:"objects"},lotion_bottle:{keywords:["moisturizer","sunscreen"],char:'🧴',fitzpatrick_scale:false,category:"objects"},key:{keywords:["lock","door","password"],char:'🔑',fitzpatrick_scale:false,category:"objects"},old_key:{keywords:["lock","door","password"],char:'🗝',fitzpatrick_scale:false,category:"objects"},couch_and_lamp:{keywords:["read","chill"],char:'🛋',fitzpatrick_scale:false,category:"objects"},sleeping_bed:{keywords:["bed","rest"],char:'🛌',fitzpatrick_scale:true,category:"objects"},bed:{keywords:["sleep","rest"],char:'🛏',fitzpatrick_scale:false,category:"objects"},door:{keywords:["house","entry","exit"],char:'🚪',fitzpatrick_scale:false,category:"objects"},bellhop_bell:{keywords:["service"],char:'🛎',fitzpatrick_scale:false,category:"objects"},teddy_bear:{keywords:["plush","stuffed"],char:'🧸',fitzpatrick_scale:false,category:"objects"},framed_picture:{keywords:["photography"],char:'🖼',fitzpatrick_scale:false,category:"objects"},world_map:{keywords:["location","direction"],char:'🗺',fitzpatrick_scale:false,category:"objects"},parasol_on_ground:{keywords:["weather","summer"],char:'⛱',fitzpatrick_scale:false,category:"objects"},moyai:{keywords:["rock","easter island","moai"],char:'🗿',fitzpatrick_scale:false,category:"objects"},shopping:{keywords:["mall","buy","purchase"],char:'🛍',fitzpatrick_scale:false,category:"objects"},shopping_cart:{keywords:["trolley"],char:'🛒',fitzpatrick_scale:false,category:"objects"},balloon:{keywords:["party","celebration","birthday","circus"],char:'🎈',fitzpatrick_scale:false,category:"objects"},flags:{keywords:["fish","japanese","koinobori","carp","banner"],char:'🎏',fitzpatrick_scale:false,category:"objects"},ribbon:{keywords:["decoration","pink","girl","bowtie"],char:'🎀',fitzpatrick_scale:false,category:"objects"},gift:{keywords:["present","birthday","christmas","xmas"],char:'🎁',fitzpatrick_scale:false,category:"objects"},confetti_ball:{keywords:["festival","party","birthday","circus"],char:'🎊',fitzpatrick_scale:false,category:"objects"},tada:{keywords:["party","congratulations","birthday","magic","circus","celebration"],char:'🎉',fitzpatrick_scale:false,category:"objects"},dolls:{keywords:["japanese","toy","kimono"],char:'🎎',fitzpatrick_scale:false,category:"objects"},wind_chime:{keywords:["nature","ding","spring","bell"],char:'🎐',fitzpatrick_scale:false,category:"objects"},crossed_flags:{keywords:["japanese","nation","country","border"],char:'🎌',fitzpatrick_scale:false,category:"objects"},izakaya_lantern:{keywords:["light","paper","halloween","spooky"],char:'🏮',fitzpatrick_scale:false,category:"objects"},red_envelope:{keywords:["gift"],char:'🧧',fitzpatrick_scale:false,category:"objects"},email:{keywords:["letter","postal","inbox","communication"],char:'✉️',fitzpatrick_scale:false,category:"objects"},envelope_with_arrow:{keywords:["email","communication"],char:'📩',fitzpatrick_scale:false,category:"objects"},incoming_envelope:{keywords:["email","inbox"],char:'📨',fitzpatrick_scale:false,category:"objects"},"e-mail":{keywords:["communication","inbox"],char:'📧',fitzpatrick_scale:false,category:"objects"},love_letter:{keywords:["email","like","affection","envelope","valentines"],char:'💌',fitzpatrick_scale:false,category:"objects"},postbox:{keywords:["email","letter","envelope"],char:'📮',fitzpatrick_scale:false,category:"objects"},mailbox_closed:{keywords:["email","communication","inbox"],char:'📪',fitzpatrick_scale:false,category:"objects"},mailbox:{keywords:["email","inbox","communication"],char:'📫',fitzpatrick_scale:false,category:"objects"},mailbox_with_mail:{keywords:["email","inbox","communication"],char:'📬',fitzpatrick_scale:false,category:"objects"},mailbox_with_no_mail:{keywords:["email","inbox"],char:'📭',fitzpatrick_scale:false,category:"objects"},package:{keywords:["mail","gift","cardboard","box","moving"],char:'📦',fitzpatrick_scale:false,category:"objects"},postal_horn:{keywords:["instrument","music"],char:'📯',fitzpatrick_scale:false,category:"objects"},inbox_tray:{keywords:["email","documents"],char:'📥',fitzpatrick_scale:false,category:"objects"},outbox_tray:{keywords:["inbox","email"],char:'📤',fitzpatrick_scale:false,category:"objects"},scroll:{keywords:["documents","ancient","history","paper"],char:'📜',fitzpatrick_scale:false,category:"objects"},page_with_curl:{keywords:["documents","office","paper"],char:'📃',fitzpatrick_scale:false,category:"objects"},bookmark_tabs:{keywords:["favorite","save","order","tidy"],char:'📑',fitzpatrick_scale:false,category:"objects"},receipt:{keywords:["accounting","expenses"],char:'🧾',fitzpatrick_scale:false,category:"objects"},bar_chart:{keywords:["graph","presentation","stats"],char:'📊',fitzpatrick_scale:false,category:"objects"},chart_with_upwards_trend:{keywords:["graph","presentation","stats","recovery","business","economics","money","sales","good","success"],char:'📈',fitzpatrick_scale:false,category:"objects"},chart_with_downwards_trend:{keywords:["graph","presentation","stats","recession","business","economics","money","sales","bad","failure"],char:'📉',fitzpatrick_scale:false,category:"objects"},page_facing_up:{keywords:["documents","office","paper","information"],char:'📄',fitzpatrick_scale:false,category:"objects"},date:{keywords:["calendar","schedule"],char:'📅',fitzpatrick_scale:false,category:"objects"},calendar:{keywords:["schedule","date","planning"],char:'📆',fitzpatrick_scale:false,category:"objects"},spiral_calendar:{keywords:["date","schedule","planning"],char:'🗓',fitzpatrick_scale:false,category:"objects"},card_index:{keywords:["business","stationery"],char:'📇',fitzpatrick_scale:false,category:"objects"},card_file_box:{keywords:["business","stationery"],char:'🗃',fitzpatrick_scale:false,category:"objects"},ballot_box:{keywords:["election","vote"],char:'🗳',fitzpatrick_scale:false,category:"objects"},file_cabinet:{keywords:["filing","organizing"],char:'🗄',fitzpatrick_scale:false,category:"objects"},clipboard:{keywords:["stationery","documents"],char:'📋',fitzpatrick_scale:false,category:"objects"},spiral_notepad:{keywords:["memo","stationery"],char:'🗒',fitzpatrick_scale:false,category:"objects"},file_folder:{keywords:["documents","business","office"],char:'📁',fitzpatrick_scale:false,category:"objects"},open_file_folder:{keywords:["documents","load"],char:'📂',fitzpatrick_scale:false,category:"objects"},card_index_dividers:{keywords:["organizing","business","stationery"],char:'🗂',fitzpatrick_scale:false,category:"objects"},newspaper_roll:{keywords:["press","headline"],char:'🗞',fitzpatrick_scale:false,category:"objects"},newspaper:{keywords:["press","headline"],char:'📰',fitzpatrick_scale:false,category:"objects"},notebook:{keywords:["stationery","record","notes","paper","study"],char:'📓',fitzpatrick_scale:false,category:"objects"},closed_book:{keywords:["read","library","knowledge","textbook","learn"],char:'📕',fitzpatrick_scale:false,category:"objects"},green_book:{keywords:["read","library","knowledge","study"],char:'📗',fitzpatrick_scale:false,category:"objects"},blue_book:{keywords:["read","library","knowledge","learn","study"],char:'📘',fitzpatrick_scale:false,category:"objects"},orange_book:{keywords:["read","library","knowledge","textbook","study"],char:'📙',fitzpatrick_scale:false,category:"objects"},notebook_with_decorative_cover:{keywords:["classroom","notes","record","paper","study"],char:'📔',fitzpatrick_scale:false,category:"objects"},ledger:{keywords:["notes","paper"],char:'📒',fitzpatrick_scale:false,category:"objects"},books:{keywords:["literature","library","study"],char:'📚',fitzpatrick_scale:false,category:"objects"},open_book:{keywords:["book","read","library","knowledge","literature","learn","study"],char:'📖',fitzpatrick_scale:false,category:"objects"},safety_pin:{keywords:["diaper"],char:'🧷',fitzpatrick_scale:false,category:"objects"},link:{keywords:["rings","url"],char:'🔗',fitzpatrick_scale:false,category:"objects"},paperclip:{keywords:["documents","stationery"],char:'📎',fitzpatrick_scale:false,category:"objects"},paperclips:{keywords:["documents","stationery"],char:'🖇',fitzpatrick_scale:false,category:"objects"},scissors:{keywords:["stationery","cut"],char:'✂️',fitzpatrick_scale:false,category:"objects"},triangular_ruler:{keywords:["stationery","math","architect","sketch"],char:'📐',fitzpatrick_scale:false,category:"objects"},straight_ruler:{keywords:["stationery","calculate","length","math","school","drawing","architect","sketch"],char:'📏',fitzpatrick_scale:false,category:"objects"},abacus:{keywords:["calculation"],char:'🧮',fitzpatrick_scale:false,category:"objects"},pushpin:{keywords:["stationery","mark","here"],char:'📌',fitzpatrick_scale:false,category:"objects"},round_pushpin:{keywords:["stationery","location","map","here"],char:'📍',fitzpatrick_scale:false,category:"objects"},triangular_flag_on_post:{keywords:["mark","milestone","place"],char:'🚩',fitzpatrick_scale:false,category:"objects"},white_flag:{keywords:["losing","loser","lost","surrender","give up","fail"],char:'🏳',fitzpatrick_scale:false,category:"objects"},black_flag:{keywords:["pirate"],char:'🏴',fitzpatrick_scale:false,category:"objects"},rainbow_flag:{keywords:["flag","rainbow","pride","gay","lgbt","glbt","queer","homosexual","lesbian","bisexual","transgender"],char:'🏳️‍🌈',fitzpatrick_scale:false,category:"objects"},closed_lock_with_key:{keywords:["security","privacy"],char:'🔐',fitzpatrick_scale:false,category:"objects"},lock:{keywords:["security","password","padlock"],char:'🔒',fitzpatrick_scale:false,category:"objects"},unlock:{keywords:["privacy","security"],char:'🔓',fitzpatrick_scale:false,category:"objects"},lock_with_ink_pen:{keywords:["security","secret"],char:'🔏',fitzpatrick_scale:false,category:"objects"},pen:{keywords:["stationery","writing","write"],char:'🖊',fitzpatrick_scale:false,category:"objects"},fountain_pen:{keywords:["stationery","writing","write"],char:'🖋',fitzpatrick_scale:false,category:"objects"},black_nib:{keywords:["pen","stationery","writing","write"],char:'✒️',fitzpatrick_scale:false,category:"objects"},memo:{keywords:["write","documents","stationery","pencil","paper","writing","legal","exam","quiz","test","study","compose"],char:'📝',fitzpatrick_scale:false,category:"objects"},pencil2:{keywords:["stationery","write","paper","writing","school","study"],char:'✏️',fitzpatrick_scale:false,category:"objects"},crayon:{keywords:["drawing","creativity"],char:'🖍',fitzpatrick_scale:false,category:"objects"},paintbrush:{keywords:["drawing","creativity","art"],char:'🖌',fitzpatrick_scale:false,category:"objects"},mag:{keywords:["search","zoom","find","detective"],char:'🔍',fitzpatrick_scale:false,category:"objects"},mag_right:{keywords:["search","zoom","find","detective"],char:'🔎',fitzpatrick_scale:false,category:"objects"},heart:{keywords:["love","like","valentines"],char:'❤️',fitzpatrick_scale:false,category:"symbols"},orange_heart:{keywords:["love","like","affection","valentines"],char:'🧡',fitzpatrick_scale:false,category:"symbols"},yellow_heart:{keywords:["love","like","affection","valentines"],char:'💛',fitzpatrick_scale:false,category:"symbols"},green_heart:{keywords:["love","like","affection","valentines"],char:'💚',fitzpatrick_scale:false,category:"symbols"},blue_heart:{keywords:["love","like","affection","valentines"],char:'💙',fitzpatrick_scale:false,category:"symbols"},purple_heart:{keywords:["love","like","affection","valentines"],char:'💜',fitzpatrick_scale:false,category:"symbols"},black_heart:{keywords:["evil"],char:'🖤',fitzpatrick_scale:false,category:"symbols"},broken_heart:{keywords:["sad","sorry","break","heart","heartbreak"],char:'💔',fitzpatrick_scale:false,category:"symbols"},heavy_heart_exclamation:{keywords:["decoration","love"],char:'❣',fitzpatrick_scale:false,category:"symbols"},two_hearts:{keywords:["love","like","affection","valentines","heart"],char:'💕',fitzpatrick_scale:false,category:"symbols"},revolving_hearts:{keywords:["love","like","affection","valentines"],char:'💞',fitzpatrick_scale:false,category:"symbols"},heartbeat:{keywords:["love","like","affection","valentines","pink","heart"],char:'💓',fitzpatrick_scale:false,category:"symbols"},heartpulse:{keywords:["like","love","affection","valentines","pink"],char:'💗',fitzpatrick_scale:false,category:"symbols"},sparkling_heart:{keywords:["love","like","affection","valentines"],char:'💖',fitzpatrick_scale:false,category:"symbols"},cupid:{keywords:["love","like","heart","affection","valentines"],char:'💘',fitzpatrick_scale:false,category:"symbols"},gift_heart:{keywords:["love","valentines"],char:'💝',fitzpatrick_scale:false,category:"symbols"},heart_decoration:{keywords:["purple-square","love","like"],char:'💟',fitzpatrick_scale:false,category:"symbols"},peace_symbol:{keywords:["hippie"],char:'☮',fitzpatrick_scale:false,category:"symbols"},latin_cross:{keywords:["christianity"],char:'✝',fitzpatrick_scale:false,category:"symbols"},star_and_crescent:{keywords:["islam"],char:'☪',fitzpatrick_scale:false,category:"symbols"},om:{keywords:["hinduism","buddhism","sikhism","jainism"],char:'🕉',fitzpatrick_scale:false,category:"symbols"},wheel_of_dharma:{keywords:["hinduism","buddhism","sikhism","jainism"],char:'☸',fitzpatrick_scale:false,category:"symbols"},star_of_david:{keywords:["judaism"],char:'✡',fitzpatrick_scale:false,category:"symbols"},six_pointed_star:{keywords:["purple-square","religion","jewish","hexagram"],char:'🔯',fitzpatrick_scale:false,category:"symbols"},menorah:{keywords:["hanukkah","candles","jewish"],char:'🕎',fitzpatrick_scale:false,category:"symbols"},yin_yang:{keywords:["balance"],char:'☯',fitzpatrick_scale:false,category:"symbols"},orthodox_cross:{keywords:["suppedaneum","religion"],char:'☦',fitzpatrick_scale:false,category:"symbols"},place_of_worship:{keywords:["religion","church","temple","prayer"],char:'🛐',fitzpatrick_scale:false,category:"symbols"},ophiuchus:{keywords:["sign","purple-square","constellation","astrology"],char:'⛎',fitzpatrick_scale:false,category:"symbols"},aries:{keywords:["sign","purple-square","zodiac","astrology"],char:'♈',fitzpatrick_scale:false,category:"symbols"},taurus:{keywords:["purple-square","sign","zodiac","astrology"],char:'♉',fitzpatrick_scale:false,category:"symbols"},gemini:{keywords:["sign","zodiac","purple-square","astrology"],char:'♊',fitzpatrick_scale:false,category:"symbols"},cancer:{keywords:["sign","zodiac","purple-square","astrology"],char:'♋',fitzpatrick_scale:false,category:"symbols"},leo:{keywords:["sign","purple-square","zodiac","astrology"],char:'♌',fitzpatrick_scale:false,category:"symbols"},virgo:{keywords:["sign","zodiac","purple-square","astrology"],char:'♍',fitzpatrick_scale:false,category:"symbols"},libra:{keywords:["sign","purple-square","zodiac","astrology"],char:'♎',fitzpatrick_scale:false,category:"symbols"},scorpius:{keywords:["sign","zodiac","purple-square","astrology","scorpio"],char:'♏',fitzpatrick_scale:false,category:"symbols"},sagittarius:{keywords:["sign","zodiac","purple-square","astrology"],char:'♐',fitzpatrick_scale:false,category:"symbols"},capricorn:{keywords:["sign","zodiac","purple-square","astrology"],char:'♑',fitzpatrick_scale:false,category:"symbols"},aquarius:{keywords:["sign","purple-square","zodiac","astrology"],char:'♒',fitzpatrick_scale:false,category:"symbols"},pisces:{keywords:["purple-square","sign","zodiac","astrology"],char:'♓',fitzpatrick_scale:false,category:"symbols"},id:{keywords:["purple-square","words"],char:'🆔',fitzpatrick_scale:false,category:"symbols"},atom_symbol:{keywords:["science","physics","chemistry"],char:'⚛',fitzpatrick_scale:false,category:"symbols"},u7a7a:{keywords:["kanji","japanese","chinese","empty","sky","blue-square"],char:'🈳',fitzpatrick_scale:false,category:"symbols"},u5272:{keywords:["cut","divide","chinese","kanji","pink-square"],char:'🈹',fitzpatrick_scale:false,category:"symbols"},radioactive:{keywords:["nuclear","danger"],char:'☢',fitzpatrick_scale:false,category:"symbols"},biohazard:{keywords:["danger"],char:'☣',fitzpatrick_scale:false,category:"symbols"},mobile_phone_off:{keywords:["mute","orange-square","silence","quiet"],char:'📴',fitzpatrick_scale:false,category:"symbols"},vibration_mode:{keywords:["orange-square","phone"],char:'📳',fitzpatrick_scale:false,category:"symbols"},u6709:{keywords:["orange-square","chinese","have","kanji"],char:'🈶',fitzpatrick_scale:false,category:"symbols"},u7121:{keywords:["nothing","chinese","kanji","japanese","orange-square"],char:'🈚',fitzpatrick_scale:false,category:"symbols"},u7533:{keywords:["chinese","japanese","kanji","orange-square"],char:'🈸',fitzpatrick_scale:false,category:"symbols"},u55b6:{keywords:["japanese","opening hours","orange-square"],char:'🈺',fitzpatrick_scale:false,category:"symbols"},u6708:{keywords:["chinese","month","moon","japanese","orange-square","kanji"],char:'🈷️',fitzpatrick_scale:false,category:"symbols"},eight_pointed_black_star:{keywords:["orange-square","shape","polygon"],char:'✴️',fitzpatrick_scale:false,category:"symbols"},vs:{keywords:["words","orange-square"],char:'🆚',fitzpatrick_scale:false,category:"symbols"},accept:{keywords:["ok","good","chinese","kanji","agree","yes","orange-circle"],char:'🉑',fitzpatrick_scale:false,category:"symbols"},white_flower:{keywords:["japanese","spring"],char:'💮',fitzpatrick_scale:false,category:"symbols"},ideograph_advantage:{keywords:["chinese","kanji","obtain","get","circle"],char:'🉐',fitzpatrick_scale:false,category:"symbols"},secret:{keywords:["privacy","chinese","sshh","kanji","red-circle"],char:'㊙️',fitzpatrick_scale:false,category:"symbols"},congratulations:{keywords:["chinese","kanji","japanese","red-circle"],char:'㊗️',fitzpatrick_scale:false,category:"symbols"},u5408:{keywords:["japanese","chinese","join","kanji","red-square"],char:'🈴',fitzpatrick_scale:false,category:"symbols"},u6e80:{keywords:["full","chinese","japanese","red-square","kanji"],char:'🈵',fitzpatrick_scale:false,category:"symbols"},u7981:{keywords:["kanji","japanese","chinese","forbidden","limit","restricted","red-square"],char:'🈲',fitzpatrick_scale:false,category:"symbols"},a:{keywords:["red-square","alphabet","letter"],char:'🅰️',fitzpatrick_scale:false,category:"symbols"},b:{keywords:["red-square","alphabet","letter"],char:'🅱️',fitzpatrick_scale:false,category:"symbols"},ab:{keywords:["red-square","alphabet"],char:'🆎',fitzpatrick_scale:false,category:"symbols"},cl:{keywords:["alphabet","words","red-square"],char:'🆑',fitzpatrick_scale:false,category:"symbols"},o2:{keywords:["alphabet","red-square","letter"],char:'🅾️',fitzpatrick_scale:false,category:"symbols"},sos:{keywords:["help","red-square","words","emergency","911"],char:'🆘',fitzpatrick_scale:false,category:"symbols"},no_entry:{keywords:["limit","security","privacy","bad","denied","stop","circle"],char:'⛔',fitzpatrick_scale:false,category:"symbols"},name_badge:{keywords:["fire","forbid"],char:'📛',fitzpatrick_scale:false,category:"symbols"},no_entry_sign:{keywords:["forbid","stop","limit","denied","disallow","circle"],char:'🚫',fitzpatrick_scale:false,category:"symbols"},x:{keywords:["no","delete","remove","cancel","red"],char:'❌',fitzpatrick_scale:false,category:"symbols"},o:{keywords:["circle","round"],char:'⭕',fitzpatrick_scale:false,category:"symbols"},stop_sign:{keywords:["stop"],char:'🛑',fitzpatrick_scale:false,category:"symbols"},anger:{keywords:["angry","mad"],char:'💢',fitzpatrick_scale:false,category:"symbols"},hotsprings:{keywords:["bath","warm","relax"],char:'♨️',fitzpatrick_scale:false,category:"symbols"},no_pedestrians:{keywords:["rules","crossing","walking","circle"],char:'🚷',fitzpatrick_scale:false,category:"symbols"},do_not_litter:{keywords:["trash","bin","garbage","circle"],char:'🚯',fitzpatrick_scale:false,category:"symbols"},no_bicycles:{keywords:["cyclist","prohibited","circle"],char:'🚳',fitzpatrick_scale:false,category:"symbols"},"non-potable_water":{keywords:["drink","faucet","tap","circle"],char:'🚱',fitzpatrick_scale:false,category:"symbols"},underage:{keywords:["18","drink","pub","night","minor","circle"],char:'🔞',fitzpatrick_scale:false,category:"symbols"},no_mobile_phones:{keywords:["iphone","mute","circle"],char:'📵',fitzpatrick_scale:false,category:"symbols"},exclamation:{keywords:["heavy_exclamation_mark","danger","surprise","punctuation","wow","warning"],char:'❗',fitzpatrick_scale:false,category:"symbols"},grey_exclamation:{keywords:["surprise","punctuation","gray","wow","warning"],char:'❕',fitzpatrick_scale:false,category:"symbols"},question:{keywords:["doubt","confused"],char:'❓',fitzpatrick_scale:false,category:"symbols"},grey_question:{keywords:["doubts","gray","huh","confused"],char:'❔',fitzpatrick_scale:false,category:"symbols"},bangbang:{keywords:["exclamation","surprise"],char:'‼️',fitzpatrick_scale:false,category:"symbols"},interrobang:{keywords:["wat","punctuation","surprise"],char:'⁉️',fitzpatrick_scale:false,category:"symbols"},low_brightness:{keywords:["sun","afternoon","warm","summer"],char:'🔅',fitzpatrick_scale:false,category:"symbols"},high_brightness:{keywords:["sun","light"],char:'🔆',fitzpatrick_scale:false,category:"symbols"},trident:{keywords:["weapon","spear"],char:'🔱',fitzpatrick_scale:false,category:"symbols"},fleur_de_lis:{keywords:["decorative","scout"],char:'⚜',fitzpatrick_scale:false,category:"symbols"},part_alternation_mark:{keywords:["graph","presentation","stats","business","economics","bad"],char:'〽️',fitzpatrick_scale:false,category:"symbols"},warning:{keywords:["exclamation","wip","alert","error","problem","issue"],char:'⚠️',fitzpatrick_scale:false,category:"symbols"},children_crossing:{keywords:["school","warning","danger","sign","driving","yellow-diamond"],char:'🚸',fitzpatrick_scale:false,category:"symbols"},beginner:{keywords:["badge","shield"],char:'🔰',fitzpatrick_scale:false,category:"symbols"},recycle:{keywords:["arrow","environment","garbage","trash"],char:'♻️',fitzpatrick_scale:false,category:"symbols"},u6307:{keywords:["chinese","point","green-square","kanji"],char:'🈯',fitzpatrick_scale:false,category:"symbols"},chart:{keywords:["green-square","graph","presentation","stats"],char:'💹',fitzpatrick_scale:false,category:"symbols"},sparkle:{keywords:["stars","green-square","awesome","good","fireworks"],char:'❇️',fitzpatrick_scale:false,category:"symbols"},eight_spoked_asterisk:{keywords:["star","sparkle","green-square"],char:'✳️',fitzpatrick_scale:false,category:"symbols"},negative_squared_cross_mark:{keywords:["x","green-square","no","deny"],char:'❎',fitzpatrick_scale:false,category:"symbols"},white_check_mark:{keywords:["green-square","ok","agree","vote","election","answer","tick"],char:'✅',fitzpatrick_scale:false,category:"symbols"},diamond_shape_with_a_dot_inside:{keywords:["jewel","blue","gem","crystal","fancy"],char:'💠',fitzpatrick_scale:false,category:"symbols"},cyclone:{keywords:["weather","swirl","blue","cloud","vortex","spiral","whirlpool","spin","tornado","hurricane","typhoon"],char:'🌀',fitzpatrick_scale:false,category:"symbols"},loop:{keywords:["tape","cassette"],char:'➿',fitzpatrick_scale:false,category:"symbols"},globe_with_meridians:{keywords:["earth","international","world","internet","interweb","i18n"],char:'🌐',fitzpatrick_scale:false,category:"symbols"},m:{keywords:["alphabet","blue-circle","letter"],char:'Ⓜ️',fitzpatrick_scale:false,category:"symbols"},atm:{keywords:["money","sales","cash","blue-square","payment","bank"],char:'🏧',fitzpatrick_scale:false,category:"symbols"},sa:{keywords:["japanese","blue-square","katakana"],char:'🈂️',fitzpatrick_scale:false,category:"symbols"},passport_control:{keywords:["custom","blue-square"],char:'🛂',fitzpatrick_scale:false,category:"symbols"},customs:{keywords:["passport","border","blue-square"],char:'🛃',fitzpatrick_scale:false,category:"symbols"},baggage_claim:{keywords:["blue-square","airport","transport"],char:'🛄',fitzpatrick_scale:false,category:"symbols"},left_luggage:{keywords:["blue-square","travel"],char:'🛅',fitzpatrick_scale:false,category:"symbols"},wheelchair:{keywords:["blue-square","disabled","a11y","accessibility"],char:'♿',fitzpatrick_scale:false,category:"symbols"},no_smoking:{keywords:["cigarette","blue-square","smell","smoke"],char:'🚭',fitzpatrick_scale:false,category:"symbols"},wc:{keywords:["toilet","restroom","blue-square"],char:'🚾',fitzpatrick_scale:false,category:"symbols"},parking:{keywords:["cars","blue-square","alphabet","letter"],char:'🅿️',fitzpatrick_scale:false,category:"symbols"},potable_water:{keywords:["blue-square","liquid","restroom","cleaning","faucet"],char:'🚰',fitzpatrick_scale:false,category:"symbols"},mens:{keywords:["toilet","restroom","wc","blue-square","gender","male"],char:'🚹',fitzpatrick_scale:false,category:"symbols"},womens:{keywords:["purple-square","woman","female","toilet","loo","restroom","gender"],char:'🚺',fitzpatrick_scale:false,category:"symbols"},baby_symbol:{keywords:["orange-square","child"],char:'🚼',fitzpatrick_scale:false,category:"symbols"},restroom:{keywords:["blue-square","toilet","refresh","wc","gender"],char:'🚻',fitzpatrick_scale:false,category:"symbols"},put_litter_in_its_place:{keywords:["blue-square","sign","human","info"],char:'🚮',fitzpatrick_scale:false,category:"symbols"},cinema:{keywords:["blue-square","record","film","movie","curtain","stage","theater"],char:'🎦',fitzpatrick_scale:false,category:"symbols"},signal_strength:{keywords:["blue-square","reception","phone","internet","connection","wifi","bluetooth","bars"],char:'📶',fitzpatrick_scale:false,category:"symbols"},koko:{keywords:["blue-square","here","katakana","japanese","destination"],char:'🈁',fitzpatrick_scale:false,category:"symbols"},ng:{keywords:["blue-square","words","shape","icon"],char:'🆖',fitzpatrick_scale:false,category:"symbols"},ok:{keywords:["good","agree","yes","blue-square"],char:'🆗',fitzpatrick_scale:false,category:"symbols"},up:{keywords:["blue-square","above","high"],char:'🆙',fitzpatrick_scale:false,category:"symbols"},cool:{keywords:["words","blue-square"],char:'🆒',fitzpatrick_scale:false,category:"symbols"},new:{keywords:["blue-square","words","start"],char:'🆕',fitzpatrick_scale:false,category:"symbols"},free:{keywords:["blue-square","words"],char:'🆓',fitzpatrick_scale:false,category:"symbols"},zero:{keywords:["0","numbers","blue-square","null"],char:'0️⃣',fitzpatrick_scale:false,category:"symbols"},one:{keywords:["blue-square","numbers","1"],char:'1️⃣',fitzpatrick_scale:false,category:"symbols"},two:{keywords:["numbers","2","prime","blue-square"],char:'2️⃣',fitzpatrick_scale:false,category:"symbols"},three:{keywords:["3","numbers","prime","blue-square"],char:'3️⃣',fitzpatrick_scale:false,category:"symbols"},four:{keywords:["4","numbers","blue-square"],char:'4️⃣',fitzpatrick_scale:false,category:"symbols"},five:{keywords:["5","numbers","blue-square","prime"],char:'5️⃣',fitzpatrick_scale:false,category:"symbols"},six:{keywords:["6","numbers","blue-square"],char:'6️⃣',fitzpatrick_scale:false,category:"symbols"},seven:{keywords:["7","numbers","blue-square","prime"],char:'7️⃣',fitzpatrick_scale:false,category:"symbols"},eight:{keywords:["8","blue-square","numbers"],char:'8️⃣',fitzpatrick_scale:false,category:"symbols"},nine:{keywords:["blue-square","numbers","9"],char:'9️⃣',fitzpatrick_scale:false,category:"symbols"},keycap_ten:{keywords:["numbers","10","blue-square"],char:'🔟',fitzpatrick_scale:false,category:"symbols"},asterisk:{keywords:["star","keycap"],char:'*⃣',fitzpatrick_scale:false,category:"symbols"},eject_button:{keywords:["blue-square"],char:'⏏️',fitzpatrick_scale:false,category:"symbols"},arrow_forward:{keywords:["blue-square","right","direction","play"],char:'▶️',fitzpatrick_scale:false,category:"symbols"},pause_button:{keywords:["pause","blue-square"],char:'⏸',fitzpatrick_scale:false,category:"symbols"},next_track_button:{keywords:["forward","next","blue-square"],char:'⏭',fitzpatrick_scale:false,category:"symbols"},stop_button:{keywords:["blue-square"],char:'⏹',fitzpatrick_scale:false,category:"symbols"},record_button:{keywords:["blue-square"],char:'⏺',fitzpatrick_scale:false,category:"symbols"},play_or_pause_button:{keywords:["blue-square","play","pause"],char:'⏯',fitzpatrick_scale:false,category:"symbols"},previous_track_button:{keywords:["backward"],char:'⏮',fitzpatrick_scale:false,category:"symbols"},fast_forward:{keywords:["blue-square","play","speed","continue"],char:'⏩',fitzpatrick_scale:false,category:"symbols"},rewind:{keywords:["play","blue-square"],char:'⏪',fitzpatrick_scale:false,category:"symbols"},twisted_rightwards_arrows:{keywords:["blue-square","shuffle","music","random"],char:'🔀',fitzpatrick_scale:false,category:"symbols"},repeat:{keywords:["loop","record"],char:'🔁',fitzpatrick_scale:false,category:"symbols"},repeat_one:{keywords:["blue-square","loop"],char:'🔂',fitzpatrick_scale:false,category:"symbols"},arrow_backward:{keywords:["blue-square","left","direction"],char:'◀️',fitzpatrick_scale:false,category:"symbols"},arrow_up_small:{keywords:["blue-square","triangle","direction","point","forward","top"],char:'🔼',fitzpatrick_scale:false,category:"symbols"},arrow_down_small:{keywords:["blue-square","direction","bottom"],char:'🔽',fitzpatrick_scale:false,category:"symbols"},arrow_double_up:{keywords:["blue-square","direction","top"],char:'⏫',fitzpatrick_scale:false,category:"symbols"},arrow_double_down:{keywords:["blue-square","direction","bottom"],char:'⏬',fitzpatrick_scale:false,category:"symbols"},arrow_right:{keywords:["blue-square","next"],char:'➡️',fitzpatrick_scale:false,category:"symbols"},arrow_left:{keywords:["blue-square","previous","back"],char:'⬅️',fitzpatrick_scale:false,category:"symbols"},arrow_up:{keywords:["blue-square","continue","top","direction"],char:'⬆️',fitzpatrick_scale:false,category:"symbols"},arrow_down:{keywords:["blue-square","direction","bottom"],char:'⬇️',fitzpatrick_scale:false,category:"symbols"},arrow_upper_right:{keywords:["blue-square","point","direction","diagonal","northeast"],char:'↗️',fitzpatrick_scale:false,category:"symbols"},arrow_lower_right:{keywords:["blue-square","direction","diagonal","southeast"],char:'↘️',fitzpatrick_scale:false,category:"symbols"},arrow_lower_left:{keywords:["blue-square","direction","diagonal","southwest"],char:'↙️',fitzpatrick_scale:false,category:"symbols"},arrow_upper_left:{keywords:["blue-square","point","direction","diagonal","northwest"],char:'↖️',fitzpatrick_scale:false,category:"symbols"},arrow_up_down:{keywords:["blue-square","direction","way","vertical"],char:'↕️',fitzpatrick_scale:false,category:"symbols"},left_right_arrow:{keywords:["shape","direction","horizontal","sideways"],char:'↔️',fitzpatrick_scale:false,category:"symbols"},arrows_counterclockwise:{keywords:["blue-square","sync","cycle"],char:'🔄',fitzpatrick_scale:false,category:"symbols"},arrow_right_hook:{keywords:["blue-square","return","rotate","direction"],char:'↪️',fitzpatrick_scale:false,category:"symbols"},leftwards_arrow_with_hook:{keywords:["back","return","blue-square","undo","enter"],char:'↩️',fitzpatrick_scale:false,category:"symbols"},arrow_heading_up:{keywords:["blue-square","direction","top"],char:'⤴️',fitzpatrick_scale:false,category:"symbols"},arrow_heading_down:{keywords:["blue-square","direction","bottom"],char:'⤵️',fitzpatrick_scale:false,category:"symbols"},hash:{keywords:["symbol","blue-square","twitter"],char:'#️⃣',fitzpatrick_scale:false,category:"symbols"},information_source:{keywords:["blue-square","alphabet","letter"],char:'ℹ️',fitzpatrick_scale:false,category:"symbols"},abc:{keywords:["blue-square","alphabet"],char:'🔤',fitzpatrick_scale:false,category:"symbols"},abcd:{keywords:["blue-square","alphabet"],char:'🔡',fitzpatrick_scale:false,category:"symbols"},capital_abcd:{keywords:["alphabet","words","blue-square"],char:'🔠',fitzpatrick_scale:false,category:"symbols"},symbols:{keywords:["blue-square","music","note","ampersand","percent","glyphs","characters"],char:'🔣',fitzpatrick_scale:false,category:"symbols"},musical_note:{keywords:["score","tone","sound"],char:'🎵',fitzpatrick_scale:false,category:"symbols"},notes:{keywords:["music","score"],char:'🎶',fitzpatrick_scale:false,category:"symbols"},wavy_dash:{keywords:["draw","line","moustache","mustache","squiggle","scribble"],char:'〰️',fitzpatrick_scale:false,category:"symbols"},curly_loop:{keywords:["scribble","draw","shape","squiggle"],char:'➰',fitzpatrick_scale:false,category:"symbols"},heavy_check_mark:{keywords:["ok","nike","answer","yes","tick"],char:'✔️',fitzpatrick_scale:false,category:"symbols"},arrows_clockwise:{keywords:["sync","cycle","round","repeat"],char:'🔃',fitzpatrick_scale:false,category:"symbols"},heavy_plus_sign:{keywords:["math","calculation","addition","more","increase"],char:'➕',fitzpatrick_scale:false,category:"symbols"},heavy_minus_sign:{keywords:["math","calculation","subtract","less"],char:'➖',fitzpatrick_scale:false,category:"symbols"},heavy_division_sign:{keywords:["divide","math","calculation"],char:'➗',fitzpatrick_scale:false,category:"symbols"},heavy_multiplication_x:{keywords:["math","calculation"],char:'✖️',fitzpatrick_scale:false,category:"symbols"},infinity:{keywords:["forever"],char:'♾',fitzpatrick_scale:false,category:"symbols"},heavy_dollar_sign:{keywords:["money","sales","payment","currency","buck"],char:'💲',fitzpatrick_scale:false,category:"symbols"},currency_exchange:{keywords:["money","sales","dollar","travel"],char:'💱',fitzpatrick_scale:false,category:"symbols"},copyright:{keywords:["ip","license","circle","law","legal"],char:'©️',fitzpatrick_scale:false,category:"symbols"},registered:{keywords:["alphabet","circle"],char:'®️',fitzpatrick_scale:false,category:"symbols"},tm:{keywords:["trademark","brand","law","legal"],char:'™️',fitzpatrick_scale:false,category:"symbols"},end:{keywords:["words","arrow"],char:'🔚',fitzpatrick_scale:false,category:"symbols"},back:{keywords:["arrow","words","return"],char:'🔙',fitzpatrick_scale:false,category:"symbols"},on:{keywords:["arrow","words"],char:'🔛',fitzpatrick_scale:false,category:"symbols"},top:{keywords:["words","blue-square"],char:'🔝',fitzpatrick_scale:false,category:"symbols"},soon:{keywords:["arrow","words"],char:'🔜',fitzpatrick_scale:false,category:"symbols"},ballot_box_with_check:{keywords:["ok","agree","confirm","black-square","vote","election","yes","tick"],char:'☑️',fitzpatrick_scale:false,category:"symbols"},radio_button:{keywords:["input","old","music","circle"],char:'🔘',fitzpatrick_scale:false,category:"symbols"},white_circle:{keywords:["shape","round"],char:'⚪',fitzpatrick_scale:false,category:"symbols"},black_circle:{keywords:["shape","button","round"],char:'⚫',fitzpatrick_scale:false,category:"symbols"},red_circle:{keywords:["shape","error","danger"],char:'🔴',fitzpatrick_scale:false,category:"symbols"},large_blue_circle:{keywords:["shape","icon","button"],char:'🔵',fitzpatrick_scale:false,category:"symbols"},small_orange_diamond:{keywords:["shape","jewel","gem"],char:'🔸',fitzpatrick_scale:false,category:"symbols"},small_blue_diamond:{keywords:["shape","jewel","gem"],char:'🔹',fitzpatrick_scale:false,category:"symbols"},large_orange_diamond:{keywords:["shape","jewel","gem"],char:'🔶',fitzpatrick_scale:false,category:"symbols"},large_blue_diamond:{keywords:["shape","jewel","gem"],char:'🔷',fitzpatrick_scale:false,category:"symbols"},small_red_triangle:{keywords:["shape","direction","up","top"],char:'🔺',fitzpatrick_scale:false,category:"symbols"},black_small_square:{keywords:["shape","icon"],char:'▪️',fitzpatrick_scale:false,category:"symbols"},white_small_square:{keywords:["shape","icon"],char:'▫️',fitzpatrick_scale:false,category:"symbols"},black_large_square:{keywords:["shape","icon","button"],char:'⬛',fitzpatrick_scale:false,category:"symbols"},white_large_square:{keywords:["shape","icon","stone","button"],char:'⬜',fitzpatrick_scale:false,category:"symbols"},small_red_triangle_down:{keywords:["shape","direction","bottom"],char:'🔻',fitzpatrick_scale:false,category:"symbols"},black_medium_square:{keywords:["shape","button","icon"],char:'◼️',fitzpatrick_scale:false,category:"symbols"},white_medium_square:{keywords:["shape","stone","icon"],char:'◻️',fitzpatrick_scale:false,category:"symbols"},black_medium_small_square:{keywords:["icon","shape","button"],char:'◾',fitzpatrick_scale:false,category:"symbols"},white_medium_small_square:{keywords:["shape","stone","icon","button"],char:'◽',fitzpatrick_scale:false,category:"symbols"},black_square_button:{keywords:["shape","input","frame"],char:'🔲',fitzpatrick_scale:false,category:"symbols"},white_square_button:{keywords:["shape","input"],char:'🔳',fitzpatrick_scale:false,category:"symbols"},speaker:{keywords:["sound","volume","silence","broadcast"],char:'🔈',fitzpatrick_scale:false,category:"symbols"},sound:{keywords:["volume","speaker","broadcast"],char:'🔉',fitzpatrick_scale:false,category:"symbols"},loud_sound:{keywords:["volume","noise","noisy","speaker","broadcast"],char:'🔊',fitzpatrick_scale:false,category:"symbols"},mute:{keywords:["sound","volume","silence","quiet"],char:'🔇',fitzpatrick_scale:false,category:"symbols"},mega:{keywords:["sound","speaker","volume"],char:'📣',fitzpatrick_scale:false,category:"symbols"},loudspeaker:{keywords:["volume","sound"],char:'📢',fitzpatrick_scale:false,category:"symbols"},bell:{keywords:["sound","notification","christmas","xmas","chime"],char:'🔔',fitzpatrick_scale:false,category:"symbols"},no_bell:{keywords:["sound","volume","mute","quiet","silent"],char:'🔕',fitzpatrick_scale:false,category:"symbols"},black_joker:{keywords:["poker","cards","game","play","magic"],char:'🃏',fitzpatrick_scale:false,category:"symbols"},mahjong:{keywords:["game","play","chinese","kanji"],char:'🀄',fitzpatrick_scale:false,category:"symbols"},spades:{keywords:["poker","cards","suits","magic"],char:'♠️',fitzpatrick_scale:false,category:"symbols"},clubs:{keywords:["poker","cards","magic","suits"],char:'♣️',fitzpatrick_scale:false,category:"symbols"},hearts:{keywords:["poker","cards","magic","suits"],char:'♥️',fitzpatrick_scale:false,category:"symbols"},diamonds:{keywords:["poker","cards","magic","suits"],char:'♦️',fitzpatrick_scale:false,category:"symbols"},flower_playing_cards:{keywords:["game","sunset","red"],char:'🎴',fitzpatrick_scale:false,category:"symbols"},thought_balloon:{keywords:["bubble","cloud","speech","thinking","dream"],char:'💭',fitzpatrick_scale:false,category:"symbols"},right_anger_bubble:{keywords:["caption","speech","thinking","mad"],char:'🗯',fitzpatrick_scale:false,category:"symbols"},speech_balloon:{keywords:["bubble","words","message","talk","chatting"],char:'💬',fitzpatrick_scale:false,category:"symbols"},left_speech_bubble:{keywords:["words","message","talk","chatting"],char:'🗨',fitzpatrick_scale:false,category:"symbols"},clock1:{keywords:["time","late","early","schedule"],char:'🕐',fitzpatrick_scale:false,category:"symbols"},clock2:{keywords:["time","late","early","schedule"],char:'🕑',fitzpatrick_scale:false,category:"symbols"},clock3:{keywords:["time","late","early","schedule"],char:'🕒',fitzpatrick_scale:false,category:"symbols"},clock4:{keywords:["time","late","early","schedule"],char:'🕓',fitzpatrick_scale:false,category:"symbols"},clock5:{keywords:["time","late","early","schedule"],char:'🕔',fitzpatrick_scale:false,category:"symbols"},clock6:{keywords:["time","late","early","schedule","dawn","dusk"],char:'🕕',fitzpatrick_scale:false,category:"symbols"},clock7:{keywords:["time","late","early","schedule"],char:'🕖',fitzpatrick_scale:false,category:"symbols"},clock8:{keywords:["time","late","early","schedule"],char:'🕗',fitzpatrick_scale:false,category:"symbols"},clock9:{keywords:["time","late","early","schedule"],char:'🕘',fitzpatrick_scale:false,category:"symbols"},clock10:{keywords:["time","late","early","schedule"],char:'🕙',fitzpatrick_scale:false,category:"symbols"},clock11:{keywords:["time","late","early","schedule"],char:'🕚',fitzpatrick_scale:false,category:"symbols"},clock12:{keywords:["time","noon","midnight","midday","late","early","schedule"],char:'🕛',fitzpatrick_scale:false,category:"symbols"},clock130:{keywords:["time","late","early","schedule"],char:'🕜',fitzpatrick_scale:false,category:"symbols"},clock230:{keywords:["time","late","early","schedule"],char:'🕝',fitzpatrick_scale:false,category:"symbols"},clock330:{keywords:["time","late","early","schedule"],char:'🕞',fitzpatrick_scale:false,category:"symbols"},clock430:{keywords:["time","late","early","schedule"],char:'🕟',fitzpatrick_scale:false,category:"symbols"},clock530:{keywords:["time","late","early","schedule"],char:'🕠',fitzpatrick_scale:false,category:"symbols"},clock630:{keywords:["time","late","early","schedule"],char:'🕡',fitzpatrick_scale:false,category:"symbols"},clock730:{keywords:["time","late","early","schedule"],char:'🕢',fitzpatrick_scale:false,category:"symbols"},clock830:{keywords:["time","late","early","schedule"],char:'🕣',fitzpatrick_scale:false,category:"symbols"},clock930:{keywords:["time","late","early","schedule"],char:'🕤',fitzpatrick_scale:false,category:"symbols"},clock1030:{keywords:["time","late","early","schedule"],char:'🕥',fitzpatrick_scale:false,category:"symbols"},clock1130:{keywords:["time","late","early","schedule"],char:'🕦',fitzpatrick_scale:false,category:"symbols"},clock1230:{keywords:["time","late","early","schedule"],char:'🕧',fitzpatrick_scale:false,category:"symbols"},afghanistan:{keywords:["af","flag","nation","country","banner"],char:'🇦🇫',fitzpatrick_scale:false,category:"flags"},aland_islands:{keywords:["Åland","islands","flag","nation","country","banner"],char:'🇦🇽',fitzpatrick_scale:false,category:"flags"},albania:{keywords:["al","flag","nation","country","banner"],char:'🇦🇱',fitzpatrick_scale:false,category:"flags"},algeria:{keywords:["dz","flag","nation","country","banner"],char:'🇩🇿',fitzpatrick_scale:false,category:"flags"},american_samoa:{keywords:["american","ws","flag","nation","country","banner"],char:'🇦🇸',fitzpatrick_scale:false,category:"flags"},andorra:{keywords:["ad","flag","nation","country","banner"],char:'🇦🇩',fitzpatrick_scale:false,category:"flags"},angola:{keywords:["ao","flag","nation","country","banner"],char:'🇦🇴',fitzpatrick_scale:false,category:"flags"},anguilla:{keywords:["ai","flag","nation","country","banner"],char:'🇦🇮',fitzpatrick_scale:false,category:"flags"},antarctica:{keywords:["aq","flag","nation","country","banner"],char:'🇦🇶',fitzpatrick_scale:false,category:"flags"},antigua_barbuda:{keywords:["antigua","barbuda","flag","nation","country","banner"],char:'🇦🇬',fitzpatrick_scale:false,category:"flags"},argentina:{keywords:["ar","flag","nation","country","banner"],char:'🇦🇷',fitzpatrick_scale:false,category:"flags"},armenia:{keywords:["am","flag","nation","country","banner"],char:'🇦🇲',fitzpatrick_scale:false,category:"flags"},aruba:{keywords:["aw","flag","nation","country","banner"],char:'🇦🇼',fitzpatrick_scale:false,category:"flags"},australia:{keywords:["au","flag","nation","country","banner"],char:'🇦🇺',fitzpatrick_scale:false,category:"flags"},austria:{keywords:["at","flag","nation","country","banner"],char:'🇦🇹',fitzpatrick_scale:false,category:"flags"},azerbaijan:{keywords:["az","flag","nation","country","banner"],char:'🇦🇿',fitzpatrick_scale:false,category:"flags"},bahamas:{keywords:["bs","flag","nation","country","banner"],char:'🇧🇸',fitzpatrick_scale:false,category:"flags"},bahrain:{keywords:["bh","flag","nation","country","banner"],char:'🇧🇭',fitzpatrick_scale:false,category:"flags"},bangladesh:{keywords:["bd","flag","nation","country","banner"],char:'🇧🇩',fitzpatrick_scale:false,category:"flags"},barbados:{keywords:["bb","flag","nation","country","banner"],char:'🇧🇧',fitzpatrick_scale:false,category:"flags"},belarus:{keywords:["by","flag","nation","country","banner"],char:'🇧🇾',fitzpatrick_scale:false,category:"flags"},belgium:{keywords:["be","flag","nation","country","banner"],char:'🇧🇪',fitzpatrick_scale:false,category:"flags"},belize:{keywords:["bz","flag","nation","country","banner"],char:'🇧🇿',fitzpatrick_scale:false,category:"flags"},benin:{keywords:["bj","flag","nation","country","banner"],char:'🇧🇯',fitzpatrick_scale:false,category:"flags"},bermuda:{keywords:["bm","flag","nation","country","banner"],char:'🇧🇲',fitzpatrick_scale:false,category:"flags"},bhutan:{keywords:["bt","flag","nation","country","banner"],char:'🇧🇹',fitzpatrick_scale:false,category:"flags"},bolivia:{keywords:["bo","flag","nation","country","banner"],char:'🇧🇴',fitzpatrick_scale:false,category:"flags"},caribbean_netherlands:{keywords:["bonaire","flag","nation","country","banner"],char:'🇧🇶',fitzpatrick_scale:false,category:"flags"},bosnia_herzegovina:{keywords:["bosnia","herzegovina","flag","nation","country","banner"],char:'🇧🇦',fitzpatrick_scale:false,category:"flags"},botswana:{keywords:["bw","flag","nation","country","banner"],char:'🇧🇼',fitzpatrick_scale:false,category:"flags"},brazil:{keywords:["br","flag","nation","country","banner"],char:'🇧🇷',fitzpatrick_scale:false,category:"flags"},british_indian_ocean_territory:{keywords:["british","indian","ocean","territory","flag","nation","country","banner"],char:'🇮🇴',fitzpatrick_scale:false,category:"flags"},british_virgin_islands:{keywords:["british","virgin","islands","bvi","flag","nation","country","banner"],char:'🇻🇬',fitzpatrick_scale:false,category:"flags"},brunei:{keywords:["bn","darussalam","flag","nation","country","banner"],char:'🇧🇳',fitzpatrick_scale:false,category:"flags"},bulgaria:{keywords:["bg","flag","nation","country","banner"],char:'🇧🇬',fitzpatrick_scale:false,category:"flags"},burkina_faso:{keywords:["burkina","faso","flag","nation","country","banner"],char:'🇧🇫',fitzpatrick_scale:false,category:"flags"},burundi:{keywords:["bi","flag","nation","country","banner"],char:'🇧🇮',fitzpatrick_scale:false,category:"flags"},cape_verde:{keywords:["cabo","verde","flag","nation","country","banner"],char:'🇨🇻',fitzpatrick_scale:false,category:"flags"},cambodia:{keywords:["kh","flag","nation","country","banner"],char:'🇰🇭',fitzpatrick_scale:false,category:"flags"},cameroon:{keywords:["cm","flag","nation","country","banner"],char:'🇨🇲',fitzpatrick_scale:false,category:"flags"},canada:{keywords:["ca","flag","nation","country","banner"],char:'🇨🇦',fitzpatrick_scale:false,category:"flags"},canary_islands:{keywords:["canary","islands","flag","nation","country","banner"],char:'🇮🇨',fitzpatrick_scale:false,category:"flags"},cayman_islands:{keywords:["cayman","islands","flag","nation","country","banner"],char:'🇰🇾',fitzpatrick_scale:false,category:"flags"},central_african_republic:{keywords:["central","african","republic","flag","nation","country","banner"],char:'🇨🇫',fitzpatrick_scale:false,category:"flags"},chad:{keywords:["td","flag","nation","country","banner"],char:'🇹🇩',fitzpatrick_scale:false,category:"flags"},chile:{keywords:["flag","nation","country","banner"],char:'🇨🇱',fitzpatrick_scale:false,category:"flags"},cn:{keywords:["china","chinese","prc","flag","country","nation","banner"],char:'🇨🇳',fitzpatrick_scale:false,category:"flags"},christmas_island:{keywords:["christmas","island","flag","nation","country","banner"],char:'🇨🇽',fitzpatrick_scale:false,category:"flags"},cocos_islands:{keywords:["cocos","keeling","islands","flag","nation","country","banner"],char:'🇨🇨',fitzpatrick_scale:false,category:"flags"},colombia:{keywords:["co","flag","nation","country","banner"],char:'🇨🇴',fitzpatrick_scale:false,category:"flags"},comoros:{keywords:["km","flag","nation","country","banner"],char:'🇰🇲',fitzpatrick_scale:false,category:"flags"},congo_brazzaville:{keywords:["congo","flag","nation","country","banner"],char:'🇨🇬',fitzpatrick_scale:false,category:"flags"},congo_kinshasa:{keywords:["congo","democratic","republic","flag","nation","country","banner"],char:'🇨🇩',fitzpatrick_scale:false,category:"flags"},cook_islands:{keywords:["cook","islands","flag","nation","country","banner"],char:'🇨🇰',fitzpatrick_scale:false,category:"flags"},costa_rica:{keywords:["costa","rica","flag","nation","country","banner"],char:'🇨🇷',fitzpatrick_scale:false,category:"flags"},croatia:{keywords:["hr","flag","nation","country","banner"],char:'🇭🇷',fitzpatrick_scale:false,category:"flags"},cuba:{keywords:["cu","flag","nation","country","banner"],char:'🇨🇺',fitzpatrick_scale:false,category:"flags"},curacao:{keywords:["curaçao","flag","nation","country","banner"],char:'🇨🇼',fitzpatrick_scale:false,category:"flags"},cyprus:{keywords:["cy","flag","nation","country","banner"],char:'🇨🇾',fitzpatrick_scale:false,category:"flags"},czech_republic:{keywords:["cz","flag","nation","country","banner"],char:'🇨🇿',fitzpatrick_scale:false,category:"flags"},denmark:{keywords:["dk","flag","nation","country","banner"],char:'🇩🇰',fitzpatrick_scale:false,category:"flags"},djibouti:{keywords:["dj","flag","nation","country","banner"],char:'🇩🇯',fitzpatrick_scale:false,category:"flags"},dominica:{keywords:["dm","flag","nation","country","banner"],char:'🇩🇲',fitzpatrick_scale:false,category:"flags"},dominican_republic:{keywords:["dominican","republic","flag","nation","country","banner"],char:'🇩🇴',fitzpatrick_scale:false,category:"flags"},ecuador:{keywords:["ec","flag","nation","country","banner"],char:'🇪🇨',fitzpatrick_scale:false,category:"flags"},egypt:{keywords:["eg","flag","nation","country","banner"],char:'🇪🇬',fitzpatrick_scale:false,category:"flags"},el_salvador:{keywords:["el","salvador","flag","nation","country","banner"],char:'🇸🇻',fitzpatrick_scale:false,category:"flags"},equatorial_guinea:{keywords:["equatorial","gn","flag","nation","country","banner"],char:'🇬🇶',fitzpatrick_scale:false,category:"flags"},eritrea:{keywords:["er","flag","nation","country","banner"],char:'🇪🇷',fitzpatrick_scale:false,category:"flags"},estonia:{keywords:["ee","flag","nation","country","banner"],char:'🇪🇪',fitzpatrick_scale:false,category:"flags"},ethiopia:{keywords:["et","flag","nation","country","banner"],char:'🇪🇹',fitzpatrick_scale:false,category:"flags"},eu:{keywords:["european","union","flag","banner"],char:'🇪🇺',fitzpatrick_scale:false,category:"flags"},falkland_islands:{keywords:["falkland","islands","malvinas","flag","nation","country","banner"],char:'🇫🇰',fitzpatrick_scale:false,category:"flags"},faroe_islands:{keywords:["faroe","islands","flag","nation","country","banner"],char:'🇫🇴',fitzpatrick_scale:false,category:"flags"},fiji:{keywords:["fj","flag","nation","country","banner"],char:'🇫🇯',fitzpatrick_scale:false,category:"flags"},finland:{keywords:["fi","flag","nation","country","banner"],char:'🇫🇮',fitzpatrick_scale:false,category:"flags"},fr:{keywords:["banner","flag","nation","france","french","country"],char:'🇫🇷',fitzpatrick_scale:false,category:"flags"},french_guiana:{keywords:["french","guiana","flag","nation","country","banner"],char:'🇬🇫',fitzpatrick_scale:false,category:"flags"},french_polynesia:{keywords:["french","polynesia","flag","nation","country","banner"],char:'🇵🇫',fitzpatrick_scale:false,category:"flags"},french_southern_territories:{keywords:["french","southern","territories","flag","nation","country","banner"],char:'🇹🇫',fitzpatrick_scale:false,category:"flags"},gabon:{keywords:["ga","flag","nation","country","banner"],char:'🇬🇦',fitzpatrick_scale:false,category:"flags"},gambia:{keywords:["gm","flag","nation","country","banner"],char:'🇬🇲',fitzpatrick_scale:false,category:"flags"},georgia:{keywords:["ge","flag","nation","country","banner"],char:'🇬🇪',fitzpatrick_scale:false,category:"flags"},de:{keywords:["german","nation","flag","country","banner"],char:'🇩🇪',fitzpatrick_scale:false,category:"flags"},ghana:{keywords:["gh","flag","nation","country","banner"],char:'🇬🇭',fitzpatrick_scale:false,category:"flags"},gibraltar:{keywords:["gi","flag","nation","country","banner"],char:'🇬🇮',fitzpatrick_scale:false,category:"flags"},greece:{keywords:["gr","flag","nation","country","banner"],char:'🇬🇷',fitzpatrick_scale:false,category:"flags"},greenland:{keywords:["gl","flag","nation","country","banner"],char:'🇬🇱',fitzpatrick_scale:false,category:"flags"},grenada:{keywords:["gd","flag","nation","country","banner"],char:'🇬🇩',fitzpatrick_scale:false,category:"flags"},guadeloupe:{keywords:["gp","flag","nation","country","banner"],char:'🇬🇵',fitzpatrick_scale:false,category:"flags"},guam:{keywords:["gu","flag","nation","country","banner"],char:'🇬🇺',fitzpatrick_scale:false,category:"flags"},guatemala:{keywords:["gt","flag","nation","country","banner"],char:'🇬🇹',fitzpatrick_scale:false,category:"flags"},guernsey:{keywords:["gg","flag","nation","country","banner"],char:'🇬🇬',fitzpatrick_scale:false,category:"flags"},guinea:{keywords:["gn","flag","nation","country","banner"],char:'🇬🇳',fitzpatrick_scale:false,category:"flags"},guinea_bissau:{keywords:["gw","bissau","flag","nation","country","banner"],char:'🇬🇼',fitzpatrick_scale:false,category:"flags"},guyana:{keywords:["gy","flag","nation","country","banner"],char:'🇬🇾',fitzpatrick_scale:false,category:"flags"},haiti:{keywords:["ht","flag","nation","country","banner"],char:'🇭🇹',fitzpatrick_scale:false,category:"flags"},honduras:{keywords:["hn","flag","nation","country","banner"],char:'🇭🇳',fitzpatrick_scale:false,category:"flags"},hong_kong:{keywords:["hong","kong","flag","nation","country","banner"],char:'🇭🇰',fitzpatrick_scale:false,category:"flags"},hungary:{keywords:["hu","flag","nation","country","banner"],char:'🇭🇺',fitzpatrick_scale:false,category:"flags"},iceland:{keywords:["is","flag","nation","country","banner"],char:'🇮🇸',fitzpatrick_scale:false,category:"flags"},india:{keywords:["in","flag","nation","country","banner"],char:'🇮🇳',fitzpatrick_scale:false,category:"flags"},indonesia:{keywords:["flag","nation","country","banner"],char:'🇮🇩',fitzpatrick_scale:false,category:"flags"},iran:{keywords:["iran,","islamic","republic","flag","nation","country","banner"],char:'🇮🇷',fitzpatrick_scale:false,category:"flags"},iraq:{keywords:["iq","flag","nation","country","banner"],char:'🇮🇶',fitzpatrick_scale:false,category:"flags"},ireland:{keywords:["ie","flag","nation","country","banner"],char:'🇮🇪',fitzpatrick_scale:false,category:"flags"},isle_of_man:{keywords:["isle","man","flag","nation","country","banner"],char:'🇮🇲',fitzpatrick_scale:false,category:"flags"},israel:{keywords:["il","flag","nation","country","banner"],char:'🇮🇱',fitzpatrick_scale:false,category:"flags"},it:{keywords:["italy","flag","nation","country","banner"],char:'🇮🇹',fitzpatrick_scale:false,category:"flags"},cote_divoire:{keywords:["ivory","coast","flag","nation","country","banner"],char:'🇨🇮',fitzpatrick_scale:false,category:"flags"},jamaica:{keywords:["jm","flag","nation","country","banner"],char:'🇯🇲',fitzpatrick_scale:false,category:"flags"},jp:{keywords:["japanese","nation","flag","country","banner"],char:'🇯🇵',fitzpatrick_scale:false,category:"flags"},jersey:{keywords:["je","flag","nation","country","banner"],char:'🇯🇪',fitzpatrick_scale:false,category:"flags"},jordan:{keywords:["jo","flag","nation","country","banner"],char:'🇯🇴',fitzpatrick_scale:false,category:"flags"},kazakhstan:{keywords:["kz","flag","nation","country","banner"],char:'🇰🇿',fitzpatrick_scale:false,category:"flags"},kenya:{keywords:["ke","flag","nation","country","banner"],char:'🇰🇪',fitzpatrick_scale:false,category:"flags"},kiribati:{keywords:["ki","flag","nation","country","banner"],char:'🇰🇮',fitzpatrick_scale:false,category:"flags"},kosovo:{keywords:["xk","flag","nation","country","banner"],char:'🇽🇰',fitzpatrick_scale:false,category:"flags"},kuwait:{keywords:["kw","flag","nation","country","banner"],char:'🇰🇼',fitzpatrick_scale:false,category:"flags"},kyrgyzstan:{keywords:["kg","flag","nation","country","banner"],char:'🇰🇬',fitzpatrick_scale:false,category:"flags"},laos:{keywords:["lao","democratic","republic","flag","nation","country","banner"],char:'🇱🇦',fitzpatrick_scale:false,category:"flags"},latvia:{keywords:["lv","flag","nation","country","banner"],char:'🇱🇻',fitzpatrick_scale:false,category:"flags"},lebanon:{keywords:["lb","flag","nation","country","banner"],char:'🇱🇧',fitzpatrick_scale:false,category:"flags"},lesotho:{keywords:["ls","flag","nation","country","banner"],char:'🇱🇸',fitzpatrick_scale:false,category:"flags"},liberia:{keywords:["lr","flag","nation","country","banner"],char:'🇱🇷',fitzpatrick_scale:false,category:"flags"},libya:{keywords:["ly","flag","nation","country","banner"],char:'🇱🇾',fitzpatrick_scale:false,category:"flags"},liechtenstein:{keywords:["li","flag","nation","country","banner"],char:'🇱🇮',fitzpatrick_scale:false,category:"flags"},lithuania:{keywords:["lt","flag","nation","country","banner"],char:'🇱🇹',fitzpatrick_scale:false,category:"flags"},luxembourg:{keywords:["lu","flag","nation","country","banner"],char:'🇱🇺',fitzpatrick_scale:false,category:"flags"},macau:{keywords:["macao","flag","nation","country","banner"],char:'🇲🇴',fitzpatrick_scale:false,category:"flags"},macedonia:{keywords:["macedonia,","flag","nation","country","banner"],char:'🇲🇰',fitzpatrick_scale:false,category:"flags"},madagascar:{keywords:["mg","flag","nation","country","banner"],char:'🇲🇬',fitzpatrick_scale:false,category:"flags"},malawi:{keywords:["mw","flag","nation","country","banner"],char:'🇲🇼',fitzpatrick_scale:false,category:"flags"},malaysia:{keywords:["my","flag","nation","country","banner"],char:'🇲🇾',fitzpatrick_scale:false,category:"flags"},maldives:{keywords:["mv","flag","nation","country","banner"],char:'🇲🇻',fitzpatrick_scale:false,category:"flags"},mali:{keywords:["ml","flag","nation","country","banner"],char:'🇲🇱',fitzpatrick_scale:false,category:"flags"},malta:{keywords:["mt","flag","nation","country","banner"],char:'🇲🇹',fitzpatrick_scale:false,category:"flags"},marshall_islands:{keywords:["marshall","islands","flag","nation","country","banner"],char:'🇲🇭',fitzpatrick_scale:false,category:"flags"},martinique:{keywords:["mq","flag","nation","country","banner"],char:'🇲🇶',fitzpatrick_scale:false,category:"flags"},mauritania:{keywords:["mr","flag","nation","country","banner"],char:'🇲🇷',fitzpatrick_scale:false,category:"flags"},mauritius:{keywords:["mu","flag","nation","country","banner"],char:'🇲🇺',fitzpatrick_scale:false,category:"flags"},mayotte:{keywords:["yt","flag","nation","country","banner"],char:'🇾🇹',fitzpatrick_scale:false,category:"flags"},mexico:{keywords:["mx","flag","nation","country","banner"],char:'🇲🇽',fitzpatrick_scale:false,category:"flags"},micronesia:{keywords:["micronesia,","federated","states","flag","nation","country","banner"],char:'🇫🇲',fitzpatrick_scale:false,category:"flags"},moldova:{keywords:["moldova,","republic","flag","nation","country","banner"],char:'🇲🇩',fitzpatrick_scale:false,category:"flags"},monaco:{keywords:["mc","flag","nation","country","banner"],char:'🇲🇨',fitzpatrick_scale:false,category:"flags"},mongolia:{keywords:["mn","flag","nation","country","banner"],char:'🇲🇳',fitzpatrick_scale:false,category:"flags"},montenegro:{keywords:["me","flag","nation","country","banner"],char:'🇲🇪',fitzpatrick_scale:false,category:"flags"},montserrat:{keywords:["ms","flag","nation","country","banner"],char:'🇲🇸',fitzpatrick_scale:false,category:"flags"},morocco:{keywords:["ma","flag","nation","country","banner"],char:'🇲🇦',fitzpatrick_scale:false,category:"flags"},mozambique:{keywords:["mz","flag","nation","country","banner"],char:'🇲🇿',fitzpatrick_scale:false,category:"flags"},myanmar:{keywords:["mm","flag","nation","country","banner"],char:'🇲🇲',fitzpatrick_scale:false,category:"flags"},namibia:{keywords:["na","flag","nation","country","banner"],char:'🇳🇦',fitzpatrick_scale:false,category:"flags"},nauru:{keywords:["nr","flag","nation","country","banner"],char:'🇳🇷',fitzpatrick_scale:false,category:"flags"},nepal:{keywords:["np","flag","nation","country","banner"],char:'🇳🇵',fitzpatrick_scale:false,category:"flags"},netherlands:{keywords:["nl","flag","nation","country","banner"],char:'🇳🇱',fitzpatrick_scale:false,category:"flags"},new_caledonia:{keywords:["new","caledonia","flag","nation","country","banner"],char:'🇳🇨',fitzpatrick_scale:false,category:"flags"},new_zealand:{keywords:["new","zealand","flag","nation","country","banner"],char:'🇳🇿',fitzpatrick_scale:false,category:"flags"},nicaragua:{keywords:["ni","flag","nation","country","banner"],char:'🇳🇮',fitzpatrick_scale:false,category:"flags"},niger:{keywords:["ne","flag","nation","country","banner"],char:'🇳🇪',fitzpatrick_scale:false,category:"flags"},nigeria:{keywords:["flag","nation","country","banner"],char:'🇳🇬',fitzpatrick_scale:false,category:"flags"},niue:{keywords:["nu","flag","nation","country","banner"],char:'🇳🇺',fitzpatrick_scale:false,category:"flags"},norfolk_island:{keywords:["norfolk","island","flag","nation","country","banner"],char:'🇳🇫',fitzpatrick_scale:false,category:"flags"},northern_mariana_islands:{keywords:["northern","mariana","islands","flag","nation","country","banner"],char:'🇲🇵',fitzpatrick_scale:false,category:"flags"},north_korea:{keywords:["north","korea","nation","flag","country","banner"],char:'🇰🇵',fitzpatrick_scale:false,category:"flags"},norway:{keywords:["no","flag","nation","country","banner"],char:'🇳🇴',fitzpatrick_scale:false,category:"flags"},oman:{keywords:["om_symbol","flag","nation","country","banner"],char:'🇴🇲',fitzpatrick_scale:false,category:"flags"},pakistan:{keywords:["pk","flag","nation","country","banner"],char:'🇵🇰',fitzpatrick_scale:false,category:"flags"},palau:{keywords:["pw","flag","nation","country","banner"],char:'🇵🇼',fitzpatrick_scale:false,category:"flags"},palestinian_territories:{keywords:["palestine","palestinian","territories","flag","nation","country","banner"],char:'🇵🇸',fitzpatrick_scale:false,category:"flags"},panama:{keywords:["pa","flag","nation","country","banner"],char:'🇵🇦',fitzpatrick_scale:false,category:"flags"},papua_new_guinea:{keywords:["papua","new","guinea","flag","nation","country","banner"],char:'🇵🇬',fitzpatrick_scale:false,category:"flags"},paraguay:{keywords:["py","flag","nation","country","banner"],char:'🇵🇾',fitzpatrick_scale:false,category:"flags"},peru:{keywords:["pe","flag","nation","country","banner"],char:'🇵🇪',fitzpatrick_scale:false,category:"flags"},philippines:{keywords:["ph","flag","nation","country","banner"],char:'🇵🇭',fitzpatrick_scale:false,category:"flags"},pitcairn_islands:{keywords:["pitcairn","flag","nation","country","banner"],char:'🇵🇳',fitzpatrick_scale:false,category:"flags"},poland:{keywords:["pl","flag","nation","country","banner"],char:'🇵🇱',fitzpatrick_scale:false,category:"flags"},portugal:{keywords:["pt","flag","nation","country","banner"],char:'🇵🇹',fitzpatrick_scale:false,category:"flags"},puerto_rico:{keywords:["puerto","rico","flag","nation","country","banner"],char:'🇵🇷',fitzpatrick_scale:false,category:"flags"},qatar:{keywords:["qa","flag","nation","country","banner"],char:'🇶🇦',fitzpatrick_scale:false,category:"flags"},reunion:{keywords:["réunion","flag","nation","country","banner"],char:'🇷🇪',fitzpatrick_scale:false,category:"flags"},romania:{keywords:["ro","flag","nation","country","banner"],char:'🇷🇴',fitzpatrick_scale:false,category:"flags"},ru:{keywords:["russian","federation","flag","nation","country","banner"],char:'🇷🇺',fitzpatrick_scale:false,category:"flags"},rwanda:{keywords:["rw","flag","nation","country","banner"],char:'🇷🇼',fitzpatrick_scale:false,category:"flags"},st_barthelemy:{keywords:["saint","barthélemy","flag","nation","country","banner"],char:'🇧🇱',fitzpatrick_scale:false,category:"flags"},st_helena:{keywords:["saint","helena","ascension","tristan","cunha","flag","nation","country","banner"],char:'🇸🇭',fitzpatrick_scale:false,category:"flags"},st_kitts_nevis:{keywords:["saint","kitts","nevis","flag","nation","country","banner"],char:'🇰🇳',fitzpatrick_scale:false,category:"flags"},st_lucia:{keywords:["saint","lucia","flag","nation","country","banner"],char:'🇱🇨',fitzpatrick_scale:false,category:"flags"},st_pierre_miquelon:{keywords:["saint","pierre","miquelon","flag","nation","country","banner"],char:'🇵🇲',fitzpatrick_scale:false,category:"flags"},st_vincent_grenadines:{keywords:["saint","vincent","grenadines","flag","nation","country","banner"],char:'🇻🇨',fitzpatrick_scale:false,category:"flags"},samoa:{keywords:["ws","flag","nation","country","banner"],char:'🇼🇸',fitzpatrick_scale:false,category:"flags"},san_marino:{keywords:["san","marino","flag","nation","country","banner"],char:'🇸🇲',fitzpatrick_scale:false,category:"flags"},sao_tome_principe:{keywords:["sao","tome","principe","flag","nation","country","banner"],char:'🇸🇹',fitzpatrick_scale:false,category:"flags"},saudi_arabia:{keywords:["flag","nation","country","banner"],char:'🇸🇦',fitzpatrick_scale:false,category:"flags"},senegal:{keywords:["sn","flag","nation","country","banner"],char:'🇸🇳',fitzpatrick_scale:false,category:"flags"},serbia:{keywords:["rs","flag","nation","country","banner"],char:'🇷🇸',fitzpatrick_scale:false,category:"flags"},seychelles:{keywords:["sc","flag","nation","country","banner"],char:'🇸🇨',fitzpatrick_scale:false,category:"flags"},sierra_leone:{keywords:["sierra","leone","flag","nation","country","banner"],char:'🇸🇱',fitzpatrick_scale:false,category:"flags"},singapore:{keywords:["sg","flag","nation","country","banner"],char:'🇸🇬',fitzpatrick_scale:false,category:"flags"},sint_maarten:{keywords:["sint","maarten","dutch","flag","nation","country","banner"],char:'🇸🇽',fitzpatrick_scale:false,category:"flags"},slovakia:{keywords:["sk","flag","nation","country","banner"],char:'🇸🇰',fitzpatrick_scale:false,category:"flags"},slovenia:{keywords:["si","flag","nation","country","banner"],char:'🇸🇮',fitzpatrick_scale:false,category:"flags"},solomon_islands:{keywords:["solomon","islands","flag","nation","country","banner"],char:'🇸🇧',fitzpatrick_scale:false,category:"flags"},somalia:{keywords:["so","flag","nation","country","banner"],char:'🇸🇴',fitzpatrick_scale:false,category:"flags"},south_africa:{keywords:["south","africa","flag","nation","country","banner"],char:'🇿🇦',fitzpatrick_scale:false,category:"flags"},south_georgia_south_sandwich_islands:{keywords:["south","georgia","sandwich","islands","flag","nation","country","banner"],char:'🇬🇸',fitzpatrick_scale:false,category:"flags"},kr:{keywords:["south","korea","nation","flag","country","banner"],char:'🇰🇷',fitzpatrick_scale:false,category:"flags"},south_sudan:{keywords:["south","sd","flag","nation","country","banner"],char:'🇸🇸',fitzpatrick_scale:false,category:"flags"},es:{keywords:["spain","flag","nation","country","banner"],char:'🇪🇸',fitzpatrick_scale:false,category:"flags"},sri_lanka:{keywords:["sri","lanka","flag","nation","country","banner"],char:'🇱🇰',fitzpatrick_scale:false,category:"flags"},sudan:{keywords:["sd","flag","nation","country","banner"],char:'🇸🇩',fitzpatrick_scale:false,category:"flags"},suriname:{keywords:["sr","flag","nation","country","banner"],char:'🇸🇷',fitzpatrick_scale:false,category:"flags"},swaziland:{keywords:["sz","flag","nation","country","banner"],char:'🇸🇿',fitzpatrick_scale:false,category:"flags"},sweden:{keywords:["se","flag","nation","country","banner"],char:'🇸🇪',fitzpatrick_scale:false,category:"flags"},switzerland:{keywords:["ch","flag","nation","country","banner"],char:'🇨🇭',fitzpatrick_scale:false,category:"flags"},syria:{keywords:["syrian","arab","republic","flag","nation","country","banner"],char:'🇸🇾',fitzpatrick_scale:false,category:"flags"},taiwan:{keywords:["tw","flag","nation","country","banner"],char:'🇹🇼',fitzpatrick_scale:false,category:"flags"},tajikistan:{keywords:["tj","flag","nation","country","banner"],char:'🇹🇯',fitzpatrick_scale:false,category:"flags"},tanzania:{keywords:["tanzania,","united","republic","flag","nation","country","banner"],char:'🇹🇿',fitzpatrick_scale:false,category:"flags"},thailand:{keywords:["th","flag","nation","country","banner"],char:'🇹🇭',fitzpatrick_scale:false,category:"flags"},timor_leste:{keywords:["timor","leste","flag","nation","country","banner"],char:'🇹🇱',fitzpatrick_scale:false,category:"flags"},togo:{keywords:["tg","flag","nation","country","banner"],char:'🇹🇬',fitzpatrick_scale:false,category:"flags"},tokelau:{keywords:["tk","flag","nation","country","banner"],char:'🇹🇰',fitzpatrick_scale:false,category:"flags"},tonga:{keywords:["to","flag","nation","country","banner"],char:'🇹🇴',fitzpatrick_scale:false,category:"flags"},trinidad_tobago:{keywords:["trinidad","tobago","flag","nation","country","banner"],char:'🇹🇹',fitzpatrick_scale:false,category:"flags"},tunisia:{keywords:["tn","flag","nation","country","banner"],char:'🇹🇳',fitzpatrick_scale:false,category:"flags"},tr:{keywords:["turkey","flag","nation","country","banner"],char:'🇹🇷',fitzpatrick_scale:false,category:"flags"},turkmenistan:{keywords:["flag","nation","country","banner"],char:'🇹🇲',fitzpatrick_scale:false,category:"flags"},turks_caicos_islands:{keywords:["turks","caicos","islands","flag","nation","country","banner"],char:'🇹🇨',fitzpatrick_scale:false,category:"flags"},tuvalu:{keywords:["flag","nation","country","banner"],char:'🇹🇻',fitzpatrick_scale:false,category:"flags"},uganda:{keywords:["ug","flag","nation","country","banner"],char:'🇺🇬',fitzpatrick_scale:false,category:"flags"},ukraine:{keywords:["ua","flag","nation","country","banner"],char:'🇺🇦',fitzpatrick_scale:false,category:"flags"},united_arab_emirates:{keywords:["united","arab","emirates","flag","nation","country","banner"],char:'🇦🇪',fitzpatrick_scale:false,category:"flags"},uk:{keywords:["united","kingdom","great","britain","northern","ireland","flag","nation","country","banner","british","UK","english","england","union jack"],char:'🇬🇧',fitzpatrick_scale:false,category:"flags"},england:{keywords:["flag","english"],char:'🏴󠁧󠁢󠁥󠁮󠁧󠁿',fitzpatrick_scale:false,category:"flags"},scotland:{keywords:["flag","scottish"],char:'🏴󠁧󠁢󠁳󠁣󠁴󠁿',fitzpatrick_scale:false,category:"flags"},wales:{keywords:["flag","welsh"],char:'🏴󠁧󠁢󠁷󠁬󠁳󠁿',fitzpatrick_scale:false,category:"flags"},us:{keywords:["united","states","america","flag","nation","country","banner"],char:'🇺🇸',fitzpatrick_scale:false,category:"flags"},us_virgin_islands:{keywords:["virgin","islands","us","flag","nation","country","banner"],char:'🇻🇮',fitzpatrick_scale:false,category:"flags"},uruguay:{keywords:["uy","flag","nation","country","banner"],char:'🇺🇾',fitzpatrick_scale:false,category:"flags"},uzbekistan:{keywords:["uz","flag","nation","country","banner"],char:'🇺🇿',fitzpatrick_scale:false,category:"flags"},vanuatu:{keywords:["vu","flag","nation","country","banner"],char:'🇻🇺',fitzpatrick_scale:false,category:"flags"},vatican_city:{keywords:["vatican","city","flag","nation","country","banner"],char:'🇻🇦',fitzpatrick_scale:false,category:"flags"},venezuela:{keywords:["ve","bolivarian","republic","flag","nation","country","banner"],char:'🇻🇪',fitzpatrick_scale:false,category:"flags"},vietnam:{keywords:["viet","nam","flag","nation","country","banner"],char:'🇻🇳',fitzpatrick_scale:false,category:"flags"},wallis_futuna:{keywords:["wallis","futuna","flag","nation","country","banner"],char:'🇼🇫',fitzpatrick_scale:false,category:"flags"},western_sahara:{keywords:["western","sahara","flag","nation","country","banner"],char:'🇪🇭',fitzpatrick_scale:false,category:"flags"},yemen:{keywords:["ye","flag","nation","country","banner"],char:'🇾🇪',fitzpatrick_scale:false,category:"flags"},zambia:{keywords:["zm","flag","nation","country","banner"],char:'🇿🇲',fitzpatrick_scale:false,category:"flags"},zimbabwe:{keywords:["zw","flag","nation","country","banner"],char:'🇿🇼',fitzpatrick_scale:false,category:"flags"},united_nations:{keywords:["un","flag","banner"],char:'🇺🇳',fitzpatrick_scale:false,category:"flags"},pirate_flag:{keywords:["skull","crossbones","flag","banner"],char:'🏴‍☠️',fitzpatrick_scale:false,category:"flags"}}); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/emoticons/js/emojiimages.min.js b/public/plugins/tinymce/plugins/emoticons/js/emojiimages.min.js new file mode 100644 index 000000000..37f3bcf83 --- /dev/null +++ b/public/plugins/tinymce/plugins/emoticons/js/emojiimages.min.js @@ -0,0 +1,3 @@ +// Source: npm package: emojilib +// Images provided by twemoji: https://github.com/twitter/twemoji +window.tinymce.Resource.add("tinymce.plugins.emoticons",{100:{keywords:["score","perfect","numbers","century","exam","quiz","test","pass","hundred"],char:'\u{1f4af}',fitzpatrick_scale:!1,category:"symbols"},1234:{keywords:["numbers","blue-square"],char:'\u{1f522}',fitzpatrick_scale:!1,category:"symbols"},grinning:{keywords:["face","smile","happy","joy",":D","grin"],char:'\u{1f600}',fitzpatrick_scale:!1,category:"people"},grimacing:{keywords:["face","grimace","teeth"],char:'\u{1f62c}',fitzpatrick_scale:!1,category:"people"},grin:{keywords:["face","happy","smile","joy","kawaii"],char:'\u{1f601}',fitzpatrick_scale:!1,category:"people"},joy:{keywords:["face","cry","tears","weep","happy","happytears","haha"],char:'\u{1f602}',fitzpatrick_scale:!1,category:"people"},rofl:{keywords:["face","rolling","floor","laughing","lol","haha"],char:'\u{1f923}',fitzpatrick_scale:!1,category:"people"},partying:{keywords:["face","celebration","woohoo"],char:'\u{1f973}',fitzpatrick_scale:!1,category:"people"},smiley:{keywords:["face","happy","joy","haha",":D",":)","smile","funny"],char:'\u{1f603}',fitzpatrick_scale:!1,category:"people"},smile:{keywords:["face","happy","joy","funny","haha","laugh","like",":D",":)"],char:'\u{1f604}',fitzpatrick_scale:!1,category:"people"},sweat_smile:{keywords:["face","hot","happy","laugh","sweat","smile","relief"],char:'\u{1f605}',fitzpatrick_scale:!1,category:"people"},laughing:{keywords:["happy","joy","lol","satisfied","haha","face","glad","XD","laugh"],char:'\u{1f606}',fitzpatrick_scale:!1,category:"people"},innocent:{keywords:["face","angel","heaven","halo"],char:'\u{1f607}',fitzpatrick_scale:!1,category:"people"},wink:{keywords:["face","happy","mischievous","secret",";)","smile","eye"],char:'\u{1f609}',fitzpatrick_scale:!1,category:"people"},blush:{keywords:["face","smile","happy","flushed","crush","embarrassed","shy","joy"],char:'\u{1f60a}',fitzpatrick_scale:!1,category:"people"},slightly_smiling_face:{keywords:["face","smile"],char:'\u{1f642}',fitzpatrick_scale:!1,category:"people"},upside_down_face:{keywords:["face","flipped","silly","smile"],char:'\u{1f643}',fitzpatrick_scale:!1,category:"people"},relaxed:{keywords:["face","blush","massage","happiness"],char:'\u263a\ufe0f',fitzpatrick_scale:!1,category:"people"},yum:{keywords:["happy","joy","tongue","smile","face","silly","yummy","nom","delicious","savouring"],char:'\u{1f60b}',fitzpatrick_scale:!1,category:"people"},relieved:{keywords:["face","relaxed","phew","massage","happiness"],char:'\u{1f60c}',fitzpatrick_scale:!1,category:"people"},heart_eyes:{keywords:["face","love","like","affection","valentines","infatuation","crush","heart"],char:'\u{1f60d}',fitzpatrick_scale:!1,category:"people"},smiling_face_with_three_hearts:{keywords:["face","love","like","affection","valentines","infatuation","crush","hearts","adore"],char:'\u{1f970}',fitzpatrick_scale:!1,category:"people"},kissing_heart:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:'\u{1f618}',fitzpatrick_scale:!1,category:"people"},kissing:{keywords:["love","like","face","3","valentines","infatuation","kiss"],char:'\u{1f617}',fitzpatrick_scale:!1,category:"people"},kissing_smiling_eyes:{keywords:["face","affection","valentines","infatuation","kiss"],char:'\u{1f619}',fitzpatrick_scale:!1,category:"people"},kissing_closed_eyes:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:'\u{1f61a}',fitzpatrick_scale:!1,category:"people"},stuck_out_tongue_winking_eye:{keywords:["face","prank","childish","playful","mischievous","smile","wink","tongue"],char:'\u{1f61c}',fitzpatrick_scale:!1,category:"people"},zany:{keywords:["face","goofy","crazy"],char:'\u{1f92a}',fitzpatrick_scale:!1,category:"people"},raised_eyebrow:{keywords:["face","distrust","scepticism","disapproval","disbelief","surprise"],char:'\u{1f928}',fitzpatrick_scale:!1,category:"people"},monocle:{keywords:["face","stuffy","wealthy"],char:'\u{1f9d0}',fitzpatrick_scale:!1,category:"people"},stuck_out_tongue_closed_eyes:{keywords:["face","prank","playful","mischievous","smile","tongue"],char:'\u{1f61d}',fitzpatrick_scale:!1,category:"people"},stuck_out_tongue:{keywords:["face","prank","childish","playful","mischievous","smile","tongue"],char:'\u{1f61b}',fitzpatrick_scale:!1,category:"people"},money_mouth_face:{keywords:["face","rich","dollar","money"],char:'\u{1f911}',fitzpatrick_scale:!1,category:"people"},nerd_face:{keywords:["face","nerdy","geek","dork"],char:'\u{1f913}',fitzpatrick_scale:!1,category:"people"},sunglasses:{keywords:["face","cool","smile","summer","beach","sunglass"],char:'\u{1f60e}',fitzpatrick_scale:!1,category:"people"},star_struck:{keywords:["face","smile","starry","eyes","grinning"],char:'\u{1f929}',fitzpatrick_scale:!1,category:"people"},clown_face:{keywords:["face"],char:'\u{1f921}',fitzpatrick_scale:!1,category:"people"},cowboy_hat_face:{keywords:["face","cowgirl","hat"],char:'\u{1f920}',fitzpatrick_scale:!1,category:"people"},hugs:{keywords:["face","smile","hug"],char:'\u{1f917}',fitzpatrick_scale:!1,category:"people"},smirk:{keywords:["face","smile","mean","prank","smug","sarcasm"],char:'\u{1f60f}',fitzpatrick_scale:!1,category:"people"},no_mouth:{keywords:["face","hellokitty"],char:'\u{1f636}',fitzpatrick_scale:!1,category:"people"},neutral_face:{keywords:["indifference","meh",":|","neutral"],char:'\u{1f610}',fitzpatrick_scale:!1,category:"people"},expressionless:{keywords:["face","indifferent","-_-","meh","deadpan"],char:'\u{1f611}',fitzpatrick_scale:!1,category:"people"},unamused:{keywords:["indifference","bored","straight face","serious","sarcasm","unimpressed","skeptical","dubious","side_eye"],char:'\u{1f612}',fitzpatrick_scale:!1,category:"people"},roll_eyes:{keywords:["face","eyeroll","frustrated"],char:'\u{1f644}',fitzpatrick_scale:!1,category:"people"},thinking:{keywords:["face","hmmm","think","consider"],char:'\u{1f914}',fitzpatrick_scale:!1,category:"people"},lying_face:{keywords:["face","lie","pinocchio"],char:'\u{1f925}',fitzpatrick_scale:!1,category:"people"},hand_over_mouth:{keywords:["face","whoops","shock","surprise"],char:'\u{1f92d}',fitzpatrick_scale:!1,category:"people"},shushing:{keywords:["face","quiet","shhh"],char:'\u{1f92b}',fitzpatrick_scale:!1,category:"people"},symbols_over_mouth:{keywords:["face","swearing","cursing","cussing","profanity","expletive"],char:'\u{1f92c}',fitzpatrick_scale:!1,category:"people"},exploding_head:{keywords:["face","shocked","mind","blown"],char:'\u{1f92f}',fitzpatrick_scale:!1,category:"people"},flushed:{keywords:["face","blush","shy","flattered"],char:'\u{1f633}',fitzpatrick_scale:!1,category:"people"},disappointed:{keywords:["face","sad","upset","depressed",":("],char:'\u{1f61e}',fitzpatrick_scale:!1,category:"people"},worried:{keywords:["face","concern","nervous",":("],char:'\u{1f61f}',fitzpatrick_scale:!1,category:"people"},angry:{keywords:["mad","face","annoyed","frustrated"],char:'\u{1f620}',fitzpatrick_scale:!1,category:"people"},rage:{keywords:["angry","mad","hate","despise"],char:'\u{1f621}',fitzpatrick_scale:!1,category:"people"},pensive:{keywords:["face","sad","depressed","upset"],char:'\u{1f614}',fitzpatrick_scale:!1,category:"people"},confused:{keywords:["face","indifference","huh","weird","hmmm",":/"],char:'\u{1f615}',fitzpatrick_scale:!1,category:"people"},slightly_frowning_face:{keywords:["face","frowning","disappointed","sad","upset"],char:'\u{1f641}',fitzpatrick_scale:!1,category:"people"},frowning_face:{keywords:["face","sad","upset","frown"],char:'\u2639',fitzpatrick_scale:!1,category:"people"},persevere:{keywords:["face","sick","no","upset","oops"],char:'\u{1f623}',fitzpatrick_scale:!1,category:"people"},confounded:{keywords:["face","confused","sick","unwell","oops",":S"],char:'\u{1f616}',fitzpatrick_scale:!1,category:"people"},tired_face:{keywords:["sick","whine","upset","frustrated"],char:'\u{1f62b}',fitzpatrick_scale:!1,category:"people"},weary:{keywords:["face","tired","sleepy","sad","frustrated","upset"],char:'\u{1f629}',fitzpatrick_scale:!1,category:"people"},pleading:{keywords:["face","begging","mercy"],char:'\u{1f97a}',fitzpatrick_scale:!1,category:"people"},triumph:{keywords:["face","gas","phew","proud","pride"],char:'\u{1f624}',fitzpatrick_scale:!1,category:"people"},open_mouth:{keywords:["face","surprise","impressed","wow","whoa",":O"],char:'\u{1f62e}',fitzpatrick_scale:!1,category:"people"},scream:{keywords:["face","munch","scared","omg"],char:'\u{1f631}',fitzpatrick_scale:!1,category:"people"},fearful:{keywords:["face","scared","terrified","nervous","oops","huh"],char:'\u{1f628}',fitzpatrick_scale:!1,category:"people"},cold_sweat:{keywords:["face","nervous","sweat"],char:'\u{1f630}',fitzpatrick_scale:!1,category:"people"},hushed:{keywords:["face","woo","shh"],char:'\u{1f62f}',fitzpatrick_scale:!1,category:"people"},frowning:{keywords:["face","aw","what"],char:'\u{1f626}',fitzpatrick_scale:!1,category:"people"},anguished:{keywords:["face","stunned","nervous"],char:'\u{1f627}',fitzpatrick_scale:!1,category:"people"},cry:{keywords:["face","tears","sad","depressed","upset",":'("],char:'\u{1f622}',fitzpatrick_scale:!1,category:"people"},disappointed_relieved:{keywords:["face","phew","sweat","nervous"],char:'\u{1f625}',fitzpatrick_scale:!1,category:"people"},drooling_face:{keywords:["face"],char:'\u{1f924}',fitzpatrick_scale:!1,category:"people"},sleepy:{keywords:["face","tired","rest","nap"],char:'\u{1f62a}',fitzpatrick_scale:!1,category:"people"},sweat:{keywords:["face","hot","sad","tired","exercise"],char:'\u{1f613}',fitzpatrick_scale:!1,category:"people"},hot:{keywords:["face","feverish","heat","red","sweating"],char:'\u{1f975}',fitzpatrick_scale:!1,category:"people"},cold:{keywords:["face","blue","freezing","frozen","frostbite","icicles"],char:'\u{1f976}',fitzpatrick_scale:!1,category:"people"},sob:{keywords:["face","cry","tears","sad","upset","depressed"],char:'\u{1f62d}',fitzpatrick_scale:!1,category:"people"},dizzy_face:{keywords:["spent","unconscious","xox","dizzy"],char:'\u{1f635}',fitzpatrick_scale:!1,category:"people"},astonished:{keywords:["face","xox","surprised","poisoned"],char:'\u{1f632}',fitzpatrick_scale:!1,category:"people"},zipper_mouth_face:{keywords:["face","sealed","zipper","secret"],char:'\u{1f910}',fitzpatrick_scale:!1,category:"people"},nauseated_face:{keywords:["face","vomit","gross","green","sick","throw up","ill"],char:'\u{1f922}',fitzpatrick_scale:!1,category:"people"},sneezing_face:{keywords:["face","gesundheit","sneeze","sick","allergy"],char:'\u{1f927}',fitzpatrick_scale:!1,category:"people"},vomiting:{keywords:["face","sick"],char:'\u{1f92e}',fitzpatrick_scale:!1,category:"people"},mask:{keywords:["face","sick","ill","disease"],char:'\u{1f637}',fitzpatrick_scale:!1,category:"people"},face_with_thermometer:{keywords:["sick","temperature","thermometer","cold","fever"],char:'\u{1f912}',fitzpatrick_scale:!1,category:"people"},face_with_head_bandage:{keywords:["injured","clumsy","bandage","hurt"],char:'\u{1f915}',fitzpatrick_scale:!1,category:"people"},woozy:{keywords:["face","dizzy","intoxicated","tipsy","wavy"],char:'\u{1f974}',fitzpatrick_scale:!1,category:"people"},sleeping:{keywords:["face","tired","sleepy","night","zzz"],char:'\u{1f634}',fitzpatrick_scale:!1,category:"people"},zzz:{keywords:["sleepy","tired","dream"],char:'\u{1f4a4}',fitzpatrick_scale:!1,category:"people"},poop:{keywords:["hankey","shitface","fail","turd","shit"],char:'\u{1f4a9}',fitzpatrick_scale:!1,category:"people"},smiling_imp:{keywords:["devil","horns"],char:'\u{1f608}',fitzpatrick_scale:!1,category:"people"},imp:{keywords:["devil","angry","horns"],char:'\u{1f47f}',fitzpatrick_scale:!1,category:"people"},japanese_ogre:{keywords:["monster","red","mask","halloween","scary","creepy","devil","demon","japanese","ogre"],char:'\u{1f479}',fitzpatrick_scale:!1,category:"people"},japanese_goblin:{keywords:["red","evil","mask","monster","scary","creepy","japanese","goblin"],char:'\u{1f47a}',fitzpatrick_scale:!1,category:"people"},skull:{keywords:["dead","skeleton","creepy","death"],char:'\u{1f480}',fitzpatrick_scale:!1,category:"people"},ghost:{keywords:["halloween","spooky","scary"],char:'\u{1f47b}',fitzpatrick_scale:!1,category:"people"},alien:{keywords:["UFO","paul","weird","outer_space"],char:'\u{1f47d}',fitzpatrick_scale:!1,category:"people"},robot:{keywords:["computer","machine","bot"],char:'\u{1f916}',fitzpatrick_scale:!1,category:"people"},smiley_cat:{keywords:["animal","cats","happy","smile"],char:'\u{1f63a}',fitzpatrick_scale:!1,category:"people"},smile_cat:{keywords:["animal","cats","smile"],char:'\u{1f638}',fitzpatrick_scale:!1,category:"people"},joy_cat:{keywords:["animal","cats","haha","happy","tears"],char:'\u{1f639}',fitzpatrick_scale:!1,category:"people"},heart_eyes_cat:{keywords:["animal","love","like","affection","cats","valentines","heart"],char:'\u{1f63b}',fitzpatrick_scale:!1,category:"people"},smirk_cat:{keywords:["animal","cats","smirk"],char:'\u{1f63c}',fitzpatrick_scale:!1,category:"people"},kissing_cat:{keywords:["animal","cats","kiss"],char:'\u{1f63d}',fitzpatrick_scale:!1,category:"people"},scream_cat:{keywords:["animal","cats","munch","scared","scream"],char:'\u{1f640}',fitzpatrick_scale:!1,category:"people"},crying_cat_face:{keywords:["animal","tears","weep","sad","cats","upset","cry"],char:'\u{1f63f}',fitzpatrick_scale:!1,category:"people"},pouting_cat:{keywords:["animal","cats"],char:'\u{1f63e}',fitzpatrick_scale:!1,category:"people"},palms_up:{keywords:["hands","gesture","cupped","prayer"],char:'\u{1f932}',fitzpatrick_scale:!0,category:"people"},raised_hands:{keywords:["gesture","hooray","yea","celebration","hands"],char:'\u{1f64c}',fitzpatrick_scale:!0,category:"people"},clap:{keywords:["hands","praise","applause","congrats","yay"],char:'\u{1f44f}',fitzpatrick_scale:!0,category:"people"},wave:{keywords:["hands","gesture","goodbye","solong","farewell","hello","hi","palm"],char:'\u{1f44b}',fitzpatrick_scale:!0,category:"people"},call_me_hand:{keywords:["hands","gesture"],char:'\u{1f919}',fitzpatrick_scale:!0,category:"people"},"+1":{keywords:["thumbsup","yes","awesome","good","agree","accept","cool","hand","like"],char:'\u{1f44d}',fitzpatrick_scale:!0,category:"people"},"-1":{keywords:["thumbsdown","no","dislike","hand"],char:'\u{1f44e}',fitzpatrick_scale:!0,category:"people"},facepunch:{keywords:["angry","violence","fist","hit","attack","hand"],char:'\u{1f44a}',fitzpatrick_scale:!0,category:"people"},fist:{keywords:["fingers","hand","grasp"],char:'\u270a',fitzpatrick_scale:!0,category:"people"},fist_left:{keywords:["hand","fistbump"],char:'\u{1f91b}',fitzpatrick_scale:!0,category:"people"},fist_right:{keywords:["hand","fistbump"],char:'\u{1f91c}',fitzpatrick_scale:!0,category:"people"},v:{keywords:["fingers","ohyeah","hand","peace","victory","two"],char:'\u270c',fitzpatrick_scale:!0,category:"people"},ok_hand:{keywords:["fingers","limbs","perfect","ok","okay"],char:'\u{1f44c}',fitzpatrick_scale:!0,category:"people"},raised_hand:{keywords:["fingers","stop","highfive","palm","ban"],char:'\u270b',fitzpatrick_scale:!0,category:"people"},raised_back_of_hand:{keywords:["fingers","raised","backhand"],char:'\u{1f91a}',fitzpatrick_scale:!0,category:"people"},open_hands:{keywords:["fingers","butterfly","hands","open"],char:'\u{1f450}',fitzpatrick_scale:!0,category:"people"},muscle:{keywords:["arm","flex","hand","summer","strong","biceps"],char:'\u{1f4aa}',fitzpatrick_scale:!0,category:"people"},pray:{keywords:["please","hope","wish","namaste","highfive"],char:'\u{1f64f}',fitzpatrick_scale:!0,category:"people"},foot:{keywords:["kick","stomp"],char:'\u{1f9b6}',fitzpatrick_scale:!0,category:"people"},leg:{keywords:["kick","limb"],char:'\u{1f9b5}',fitzpatrick_scale:!0,category:"people"},handshake:{keywords:["agreement","shake"],char:'\u{1f91d}',fitzpatrick_scale:!1,category:"people"},point_up:{keywords:["hand","fingers","direction","up"],char:'\u261d',fitzpatrick_scale:!0,category:"people"},point_up_2:{keywords:["fingers","hand","direction","up"],char:'\u{1f446}',fitzpatrick_scale:!0,category:"people"},point_down:{keywords:["fingers","hand","direction","down"],char:'\u{1f447}',fitzpatrick_scale:!0,category:"people"},point_left:{keywords:["direction","fingers","hand","left"],char:'\u{1f448}',fitzpatrick_scale:!0,category:"people"},point_right:{keywords:["fingers","hand","direction","right"],char:'\u{1f449}',fitzpatrick_scale:!0,category:"people"},fu:{keywords:["hand","fingers","rude","middle","flipping"],char:'\u{1f595}',fitzpatrick_scale:!0,category:"people"},raised_hand_with_fingers_splayed:{keywords:["hand","fingers","palm"],char:'\u{1f590}',fitzpatrick_scale:!0,category:"people"},love_you:{keywords:["hand","fingers","gesture"],char:'\u{1f91f}',fitzpatrick_scale:!0,category:"people"},metal:{keywords:["hand","fingers","evil_eye","sign_of_horns","rock_on"],char:'\u{1f918}',fitzpatrick_scale:!0,category:"people"},crossed_fingers:{keywords:["good","lucky"],char:'\u{1f91e}',fitzpatrick_scale:!0,category:"people"},vulcan_salute:{keywords:["hand","fingers","spock","star trek"],char:'\u{1f596}',fitzpatrick_scale:!0,category:"people"},writing_hand:{keywords:["lower_left_ballpoint_pen","stationery","write","compose"],char:'\u270d',fitzpatrick_scale:!0,category:"people"},selfie:{keywords:["camera","phone"],char:'\u{1f933}',fitzpatrick_scale:!0,category:"people"},nail_care:{keywords:["beauty","manicure","finger","fashion","nail"],char:'\u{1f485}',fitzpatrick_scale:!0,category:"people"},lips:{keywords:["mouth","kiss"],char:'\u{1f444}',fitzpatrick_scale:!1,category:"people"},tooth:{keywords:["teeth","dentist"],char:'\u{1f9b7}',fitzpatrick_scale:!1,category:"people"},tongue:{keywords:["mouth","playful"],char:'\u{1f445}',fitzpatrick_scale:!1,category:"people"},ear:{keywords:["face","hear","sound","listen"],char:'\u{1f442}',fitzpatrick_scale:!0,category:"people"},nose:{keywords:["smell","sniff"],char:'\u{1f443}',fitzpatrick_scale:!0,category:"people"},eye:{keywords:["face","look","see","watch","stare"],char:'\u{1f441}',fitzpatrick_scale:!1,category:"people"},eyes:{keywords:["look","watch","stalk","peek","see"],char:'\u{1f440}',fitzpatrick_scale:!1,category:"people"},brain:{keywords:["smart","intelligent"],char:'\u{1f9e0}',fitzpatrick_scale:!1,category:"people"},bust_in_silhouette:{keywords:["user","person","human"],char:'\u{1f464}',fitzpatrick_scale:!1,category:"people"},busts_in_silhouette:{keywords:["user","person","human","group","team"],char:'\u{1f465}',fitzpatrick_scale:!1,category:"people"},speaking_head:{keywords:["user","person","human","sing","say","talk"],char:'\u{1f5e3}',fitzpatrick_scale:!1,category:"people"},baby:{keywords:["child","boy","girl","toddler"],char:'\u{1f476}',fitzpatrick_scale:!0,category:"people"},child:{keywords:["gender-neutral","young"],char:'\u{1f9d2}',fitzpatrick_scale:!0,category:"people"},boy:{keywords:["man","male","guy","teenager"],char:'\u{1f466}',fitzpatrick_scale:!0,category:"people"},girl:{keywords:["female","woman","teenager"],char:'\u{1f467}',fitzpatrick_scale:!0,category:"people"},adult:{keywords:["gender-neutral","person"],char:'\u{1f9d1}',fitzpatrick_scale:!0,category:"people"},man:{keywords:["mustache","father","dad","guy","classy","sir","moustache"],char:'\u{1f468}',fitzpatrick_scale:!0,category:"people"},woman:{keywords:["female","girls","lady"],char:'\u{1f469}',fitzpatrick_scale:!0,category:"people"},blonde_woman:{keywords:["woman","female","girl","blonde","person"],char:'\u{1f471}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},blonde_man:{keywords:["man","male","boy","blonde","guy","person"],char:'\u{1f471}',fitzpatrick_scale:!0,category:"people"},bearded_person:{keywords:["person","bewhiskered"],char:'\u{1f9d4}',fitzpatrick_scale:!0,category:"people"},older_adult:{keywords:["human","elder","senior","gender-neutral"],char:'\u{1f9d3}',fitzpatrick_scale:!0,category:"people"},older_man:{keywords:["human","male","men","old","elder","senior"],char:'\u{1f474}',fitzpatrick_scale:!0,category:"people"},older_woman:{keywords:["human","female","women","lady","old","elder","senior"],char:'\u{1f475}',fitzpatrick_scale:!0,category:"people"},man_with_gua_pi_mao:{keywords:["male","boy","chinese"],char:'\u{1f472}',fitzpatrick_scale:!0,category:"people"},woman_with_headscarf:{keywords:["female","hijab","mantilla","tichel"],char:'\u{1f9d5}',fitzpatrick_scale:!0,category:"people"},woman_with_turban:{keywords:["female","indian","hinduism","arabs","woman"],char:'\u{1f473}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_with_turban:{keywords:["male","indian","hinduism","arabs"],char:'\u{1f473}',fitzpatrick_scale:!0,category:"people"},policewoman:{keywords:["woman","police","law","legal","enforcement","arrest","911","female"],char:'\u{1f46e}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},policeman:{keywords:["man","police","law","legal","enforcement","arrest","911"],char:'\u{1f46e}',fitzpatrick_scale:!0,category:"people"},construction_worker_woman:{keywords:["female","human","wip","build","construction","worker","labor","woman"],char:'\u{1f477}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},construction_worker_man:{keywords:["male","human","wip","guy","build","construction","worker","labor"],char:'\u{1f477}',fitzpatrick_scale:!0,category:"people"},guardswoman:{keywords:["uk","gb","british","female","royal","woman"],char:'\u{1f482}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},guardsman:{keywords:["uk","gb","british","male","guy","royal"],char:'\u{1f482}',fitzpatrick_scale:!0,category:"people"},female_detective:{keywords:["human","spy","detective","female","woman"],char:'\u{1f575}\ufe0f\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},male_detective:{keywords:["human","spy","detective"],char:'\u{1f575}',fitzpatrick_scale:!0,category:"people"},woman_health_worker:{keywords:["doctor","nurse","therapist","healthcare","woman","human"],char:'\u{1f469}\u200d\u2695\ufe0f',fitzpatrick_scale:!0,category:"people"},man_health_worker:{keywords:["doctor","nurse","therapist","healthcare","man","human"],char:'\u{1f468}\u200d\u2695\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_farmer:{keywords:["rancher","gardener","woman","human"],char:'\u{1f469}\u200d\u{1f33e}',fitzpatrick_scale:!0,category:"people"},man_farmer:{keywords:["rancher","gardener","man","human"],char:'\u{1f468}\u200d\u{1f33e}',fitzpatrick_scale:!0,category:"people"},woman_cook:{keywords:["chef","woman","human"],char:'\u{1f469}\u200d\u{1f373}',fitzpatrick_scale:!0,category:"people"},man_cook:{keywords:["chef","man","human"],char:'\u{1f468}\u200d\u{1f373}',fitzpatrick_scale:!0,category:"people"},woman_student:{keywords:["graduate","woman","human"],char:'\u{1f469}\u200d\u{1f393}',fitzpatrick_scale:!0,category:"people"},man_student:{keywords:["graduate","man","human"],char:'\u{1f468}\u200d\u{1f393}',fitzpatrick_scale:!0,category:"people"},woman_singer:{keywords:["rockstar","entertainer","woman","human"],char:'\u{1f469}\u200d\u{1f3a4}',fitzpatrick_scale:!0,category:"people"},man_singer:{keywords:["rockstar","entertainer","man","human"],char:'\u{1f468}\u200d\u{1f3a4}',fitzpatrick_scale:!0,category:"people"},woman_teacher:{keywords:["instructor","professor","woman","human"],char:'\u{1f469}\u200d\u{1f3eb}',fitzpatrick_scale:!0,category:"people"},man_teacher:{keywords:["instructor","professor","man","human"],char:'\u{1f468}\u200d\u{1f3eb}',fitzpatrick_scale:!0,category:"people"},woman_factory_worker:{keywords:["assembly","industrial","woman","human"],char:'\u{1f469}\u200d\u{1f3ed}',fitzpatrick_scale:!0,category:"people"},man_factory_worker:{keywords:["assembly","industrial","man","human"],char:'\u{1f468}\u200d\u{1f3ed}',fitzpatrick_scale:!0,category:"people"},woman_technologist:{keywords:["coder","developer","engineer","programmer","software","woman","human","laptop","computer"],char:'\u{1f469}\u200d\u{1f4bb}',fitzpatrick_scale:!0,category:"people"},man_technologist:{keywords:["coder","developer","engineer","programmer","software","man","human","laptop","computer"],char:'\u{1f468}\u200d\u{1f4bb}',fitzpatrick_scale:!0,category:"people"},woman_office_worker:{keywords:["business","manager","woman","human"],char:'\u{1f469}\u200d\u{1f4bc}',fitzpatrick_scale:!0,category:"people"},man_office_worker:{keywords:["business","manager","man","human"],char:'\u{1f468}\u200d\u{1f4bc}',fitzpatrick_scale:!0,category:"people"},woman_mechanic:{keywords:["plumber","woman","human","wrench"],char:'\u{1f469}\u200d\u{1f527}',fitzpatrick_scale:!0,category:"people"},man_mechanic:{keywords:["plumber","man","human","wrench"],char:'\u{1f468}\u200d\u{1f527}',fitzpatrick_scale:!0,category:"people"},woman_scientist:{keywords:["biologist","chemist","engineer","physicist","woman","human"],char:'\u{1f469}\u200d\u{1f52c}',fitzpatrick_scale:!0,category:"people"},man_scientist:{keywords:["biologist","chemist","engineer","physicist","man","human"],char:'\u{1f468}\u200d\u{1f52c}',fitzpatrick_scale:!0,category:"people"},woman_artist:{keywords:["painter","woman","human"],char:'\u{1f469}\u200d\u{1f3a8}',fitzpatrick_scale:!0,category:"people"},man_artist:{keywords:["painter","man","human"],char:'\u{1f468}\u200d\u{1f3a8}',fitzpatrick_scale:!0,category:"people"},woman_firefighter:{keywords:["fireman","woman","human"],char:'\u{1f469}\u200d\u{1f692}',fitzpatrick_scale:!0,category:"people"},man_firefighter:{keywords:["fireman","man","human"],char:'\u{1f468}\u200d\u{1f692}',fitzpatrick_scale:!0,category:"people"},woman_pilot:{keywords:["aviator","plane","woman","human"],char:'\u{1f469}\u200d\u2708\ufe0f',fitzpatrick_scale:!0,category:"people"},man_pilot:{keywords:["aviator","plane","man","human"],char:'\u{1f468}\u200d\u2708\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_astronaut:{keywords:["space","rocket","woman","human"],char:'\u{1f469}\u200d\u{1f680}',fitzpatrick_scale:!0,category:"people"},man_astronaut:{keywords:["space","rocket","man","human"],char:'\u{1f468}\u200d\u{1f680}',fitzpatrick_scale:!0,category:"people"},woman_judge:{keywords:["justice","court","woman","human"],char:'\u{1f469}\u200d\u2696\ufe0f',fitzpatrick_scale:!0,category:"people"},man_judge:{keywords:["justice","court","man","human"],char:'\u{1f468}\u200d\u2696\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_superhero:{keywords:["woman","female","good","heroine","superpowers"],char:'\u{1f9b8}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_superhero:{keywords:["man","male","good","hero","superpowers"],char:'\u{1f9b8}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_supervillain:{keywords:["woman","female","evil","bad","criminal","heroine","superpowers"],char:'\u{1f9b9}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_supervillain:{keywords:["man","male","evil","bad","criminal","hero","superpowers"],char:'\u{1f9b9}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},mrs_claus:{keywords:["woman","female","xmas","mother christmas"],char:'\u{1f936}',fitzpatrick_scale:!0,category:"people"},santa:{keywords:["festival","man","male","xmas","father christmas"],char:'\u{1f385}',fitzpatrick_scale:!0,category:"people"},sorceress:{keywords:["woman","female","mage","witch"],char:'\u{1f9d9}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},wizard:{keywords:["man","male","mage","sorcerer"],char:'\u{1f9d9}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_elf:{keywords:["woman","female"],char:'\u{1f9dd}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_elf:{keywords:["man","male"],char:'\u{1f9dd}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_vampire:{keywords:["woman","female"],char:'\u{1f9db}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_vampire:{keywords:["man","male","dracula"],char:'\u{1f9db}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_zombie:{keywords:["woman","female","undead","walking dead"],char:'\u{1f9df}\u200d\u2640\ufe0f',fitzpatrick_scale:!1,category:"people"},man_zombie:{keywords:["man","male","dracula","undead","walking dead"],char:'\u{1f9df}\u200d\u2642\ufe0f',fitzpatrick_scale:!1,category:"people"},woman_genie:{keywords:["woman","female"],char:'\u{1f9de}\u200d\u2640\ufe0f',fitzpatrick_scale:!1,category:"people"},man_genie:{keywords:["man","male"],char:'\u{1f9de}\u200d\u2642\ufe0f',fitzpatrick_scale:!1,category:"people"},mermaid:{keywords:["woman","female","merwoman","ariel"],char:'\u{1f9dc}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},merman:{keywords:["man","male","triton"],char:'\u{1f9dc}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_fairy:{keywords:["woman","female"],char:'\u{1f9da}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_fairy:{keywords:["man","male"],char:'\u{1f9da}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},angel:{keywords:["heaven","wings","halo"],char:'\u{1f47c}',fitzpatrick_scale:!0,category:"people"},pregnant_woman:{keywords:["baby"],char:'\u{1f930}',fitzpatrick_scale:!0,category:"people"},breastfeeding:{keywords:["nursing","baby"],char:'\u{1f931}',fitzpatrick_scale:!0,category:"people"},princess:{keywords:["girl","woman","female","blond","crown","royal","queen"],char:'\u{1f478}',fitzpatrick_scale:!0,category:"people"},prince:{keywords:["boy","man","male","crown","royal","king"],char:'\u{1f934}',fitzpatrick_scale:!0,category:"people"},bride_with_veil:{keywords:["couple","marriage","wedding","woman","bride"],char:'\u{1f470}',fitzpatrick_scale:!0,category:"people"},man_in_tuxedo:{keywords:["couple","marriage","wedding","groom"],char:'\u{1f935}',fitzpatrick_scale:!0,category:"people"},running_woman:{keywords:["woman","walking","exercise","race","running","female"],char:'\u{1f3c3}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},running_man:{keywords:["man","walking","exercise","race","running"],char:'\u{1f3c3}',fitzpatrick_scale:!0,category:"people"},walking_woman:{keywords:["human","feet","steps","woman","female"],char:'\u{1f6b6}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},walking_man:{keywords:["human","feet","steps"],char:'\u{1f6b6}',fitzpatrick_scale:!0,category:"people"},dancer:{keywords:["female","girl","woman","fun"],char:'\u{1f483}',fitzpatrick_scale:!0,category:"people"},man_dancing:{keywords:["male","boy","fun","dancer"],char:'\u{1f57a}',fitzpatrick_scale:!0,category:"people"},dancing_women:{keywords:["female","bunny","women","girls"],char:'\u{1f46f}',fitzpatrick_scale:!1,category:"people"},dancing_men:{keywords:["male","bunny","men","boys"],char:'\u{1f46f}\u200d\u2642\ufe0f',fitzpatrick_scale:!1,category:"people"},couple:{keywords:["pair","people","human","love","date","dating","like","affection","valentines","marriage"],char:'\u{1f46b}',fitzpatrick_scale:!1,category:"people"},two_men_holding_hands:{keywords:["pair","couple","love","like","bromance","friendship","people","human"],char:'\u{1f46c}',fitzpatrick_scale:!1,category:"people"},two_women_holding_hands:{keywords:["pair","friendship","couple","love","like","female","people","human"],char:'\u{1f46d}',fitzpatrick_scale:!1,category:"people"},bowing_woman:{keywords:["woman","female","girl"],char:'\u{1f647}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},bowing_man:{keywords:["man","male","boy"],char:'\u{1f647}',fitzpatrick_scale:!0,category:"people"},man_facepalming:{keywords:["man","male","boy","disbelief"],char:'\u{1f926}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_facepalming:{keywords:["woman","female","girl","disbelief"],char:'\u{1f926}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_shrugging:{keywords:["woman","female","girl","confused","indifferent","doubt"],char:'\u{1f937}',fitzpatrick_scale:!0,category:"people"},man_shrugging:{keywords:["man","male","boy","confused","indifferent","doubt"],char:'\u{1f937}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},tipping_hand_woman:{keywords:["female","girl","woman","human","information"],char:'\u{1f481}',fitzpatrick_scale:!0,category:"people"},tipping_hand_man:{keywords:["male","boy","man","human","information"],char:'\u{1f481}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},no_good_woman:{keywords:["female","girl","woman","nope"],char:'\u{1f645}',fitzpatrick_scale:!0,category:"people"},no_good_man:{keywords:["male","boy","man","nope"],char:'\u{1f645}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},ok_woman:{keywords:["women","girl","female","pink","human","woman"],char:'\u{1f646}',fitzpatrick_scale:!0,category:"people"},ok_man:{keywords:["men","boy","male","blue","human","man"],char:'\u{1f646}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},raising_hand_woman:{keywords:["female","girl","woman"],char:'\u{1f64b}',fitzpatrick_scale:!0,category:"people"},raising_hand_man:{keywords:["male","boy","man"],char:'\u{1f64b}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},pouting_woman:{keywords:["female","girl","woman"],char:'\u{1f64e}',fitzpatrick_scale:!0,category:"people"},pouting_man:{keywords:["male","boy","man"],char:'\u{1f64e}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},frowning_woman:{keywords:["female","girl","woman","sad","depressed","discouraged","unhappy"],char:'\u{1f64d}',fitzpatrick_scale:!0,category:"people"},frowning_man:{keywords:["male","boy","man","sad","depressed","discouraged","unhappy"],char:'\u{1f64d}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},haircut_woman:{keywords:["female","girl","woman"],char:'\u{1f487}',fitzpatrick_scale:!0,category:"people"},haircut_man:{keywords:["male","boy","man"],char:'\u{1f487}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},massage_woman:{keywords:["female","girl","woman","head"],char:'\u{1f486}',fitzpatrick_scale:!0,category:"people"},massage_man:{keywords:["male","boy","man","head"],char:'\u{1f486}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},woman_in_steamy_room:{keywords:["female","woman","spa","steamroom","sauna"],char:'\u{1f9d6}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"people"},man_in_steamy_room:{keywords:["male","man","spa","steamroom","sauna"],char:'\u{1f9d6}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"people"},couple_with_heart_woman_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:'\u{1f491}',fitzpatrick_scale:!1,category:"people"},couple_with_heart_woman_woman:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:'\u{1f469}\u200d\u2764\ufe0f\u200d\u{1f469}',fitzpatrick_scale:!1,category:"people"},couple_with_heart_man_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:'\u{1f468}\u200d\u2764\ufe0f\u200d\u{1f468}',fitzpatrick_scale:!1,category:"people"},couplekiss_man_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:'\u{1f48f}',fitzpatrick_scale:!1,category:"people"},couplekiss_woman_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:'\u{1f469}\u200d\u2764\ufe0f\u200d\u{1f48b}\u200d\u{1f469}',fitzpatrick_scale:!1,category:"people"},couplekiss_man_man:{keywords:["pair","valentines","love","like","dating","marriage"],char:'\u{1f468}\u200d\u2764\ufe0f\u200d\u{1f48b}\u200d\u{1f468}',fitzpatrick_scale:!1,category:"people"},family_man_woman_boy:{keywords:["home","parents","child","mom","dad","father","mother","people","human"],char:'\u{1f46a}',fitzpatrick_scale:!1,category:"people"},family_man_woman_girl:{keywords:["home","parents","people","human","child"],char:'\u{1f468}\u200d\u{1f469}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_man_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f469}\u200d\u{1f466}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_woman_woman_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f469}\u200d\u{1f469}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl:{keywords:["home","parents","people","human","children"],char:'\u{1f469}\u200d\u{1f469}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f469}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_woman_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f469}\u200d\u{1f469}\u200d\u{1f466}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:'\u{1f469}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_man_man_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f468}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_man_girl:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f468}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_man_man_girl_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f468}\u200d\u{1f467}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_man_boy_boy:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f468}\u200d\u{1f466}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_man_girl_girl:{keywords:["home","parents","people","human","children"],char:'\u{1f468}\u200d\u{1f468}\u200d\u{1f467}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_woman_boy:{keywords:["home","parent","people","human","child"],char:'\u{1f469}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_woman_girl:{keywords:["home","parent","people","human","child"],char:'\u{1f469}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_woman_girl_boy:{keywords:["home","parent","people","human","children"],char:'\u{1f469}\u200d\u{1f467}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_woman_boy_boy:{keywords:["home","parent","people","human","children"],char:'\u{1f469}\u200d\u{1f466}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_woman_girl_girl:{keywords:["home","parent","people","human","children"],char:'\u{1f469}\u200d\u{1f467}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_man_boy:{keywords:["home","parent","people","human","child"],char:'\u{1f468}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_girl:{keywords:["home","parent","people","human","child"],char:'\u{1f468}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},family_man_girl_boy:{keywords:["home","parent","people","human","children"],char:'\u{1f468}\u200d\u{1f467}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_boy_boy:{keywords:["home","parent","people","human","children"],char:'\u{1f468}\u200d\u{1f466}\u200d\u{1f466}',fitzpatrick_scale:!1,category:"people"},family_man_girl_girl:{keywords:["home","parent","people","human","children"],char:'\u{1f468}\u200d\u{1f467}\u200d\u{1f467}',fitzpatrick_scale:!1,category:"people"},yarn:{keywords:["ball","crochet","knit"],char:'\u{1f9f6}',fitzpatrick_scale:!1,category:"people"},thread:{keywords:["needle","sewing","spool","string"],char:'\u{1f9f5}',fitzpatrick_scale:!1,category:"people"},coat:{keywords:["jacket"],char:'\u{1f9e5}',fitzpatrick_scale:!1,category:"people"},labcoat:{keywords:["doctor","experiment","scientist","chemist"],char:'\u{1f97c}',fitzpatrick_scale:!1,category:"people"},womans_clothes:{keywords:["fashion","shopping_bags","female"],char:'\u{1f45a}',fitzpatrick_scale:!1,category:"people"},tshirt:{keywords:["fashion","cloth","casual","shirt","tee"],char:'\u{1f455}',fitzpatrick_scale:!1,category:"people"},jeans:{keywords:["fashion","shopping"],char:'\u{1f456}',fitzpatrick_scale:!1,category:"people"},necktie:{keywords:["shirt","suitup","formal","fashion","cloth","business"],char:'\u{1f454}',fitzpatrick_scale:!1,category:"people"},dress:{keywords:["clothes","fashion","shopping"],char:'\u{1f457}',fitzpatrick_scale:!1,category:"people"},bikini:{keywords:["swimming","female","woman","girl","fashion","beach","summer"],char:'\u{1f459}',fitzpatrick_scale:!1,category:"people"},kimono:{keywords:["dress","fashion","women","female","japanese"],char:'\u{1f458}',fitzpatrick_scale:!1,category:"people"},lipstick:{keywords:["female","girl","fashion","woman"],char:'\u{1f484}',fitzpatrick_scale:!1,category:"people"},kiss:{keywords:["face","lips","love","like","affection","valentines"],char:'\u{1f48b}',fitzpatrick_scale:!1,category:"people"},footprints:{keywords:["feet","tracking","walking","beach"],char:'\u{1f463}',fitzpatrick_scale:!1,category:"people"},flat_shoe:{keywords:["ballet","slip-on","slipper"],char:'\u{1f97f}',fitzpatrick_scale:!1,category:"people"},high_heel:{keywords:["fashion","shoes","female","pumps","stiletto"],char:'\u{1f460}',fitzpatrick_scale:!1,category:"people"},sandal:{keywords:["shoes","fashion","flip flops"],char:'\u{1f461}',fitzpatrick_scale:!1,category:"people"},boot:{keywords:["shoes","fashion"],char:'\u{1f462}',fitzpatrick_scale:!1,category:"people"},mans_shoe:{keywords:["fashion","male"],char:'\u{1f45e}',fitzpatrick_scale:!1,category:"people"},athletic_shoe:{keywords:["shoes","sports","sneakers"],char:'\u{1f45f}',fitzpatrick_scale:!1,category:"people"},hiking_boot:{keywords:["backpacking","camping","hiking"],char:'\u{1f97e}',fitzpatrick_scale:!1,category:"people"},socks:{keywords:["stockings","clothes"],char:'\u{1f9e6}',fitzpatrick_scale:!1,category:"people"},gloves:{keywords:["hands","winter","clothes"],char:'\u{1f9e4}',fitzpatrick_scale:!1,category:"people"},scarf:{keywords:["neck","winter","clothes"],char:'\u{1f9e3}',fitzpatrick_scale:!1,category:"people"},womans_hat:{keywords:["fashion","accessories","female","lady","spring"],char:'\u{1f452}',fitzpatrick_scale:!1,category:"people"},tophat:{keywords:["magic","gentleman","classy","circus"],char:'\u{1f3a9}',fitzpatrick_scale:!1,category:"people"},billed_hat:{keywords:["cap","baseball"],char:'\u{1f9e2}',fitzpatrick_scale:!1,category:"people"},rescue_worker_helmet:{keywords:["construction","build"],char:'\u26d1',fitzpatrick_scale:!1,category:"people"},mortar_board:{keywords:["school","college","degree","university","graduation","cap","hat","legal","learn","education"],char:'\u{1f393}',fitzpatrick_scale:!1,category:"people"},crown:{keywords:["king","kod","leader","royalty","lord"],char:'\u{1f451}',fitzpatrick_scale:!1,category:"people"},school_satchel:{keywords:["student","education","bag","backpack"],char:'\u{1f392}',fitzpatrick_scale:!1,category:"people"},luggage:{keywords:["packing","travel"],char:'\u{1f9f3}',fitzpatrick_scale:!1,category:"people"},pouch:{keywords:["bag","accessories","shopping"],char:'\u{1f45d}',fitzpatrick_scale:!1,category:"people"},purse:{keywords:["fashion","accessories","money","sales","shopping"],char:'\u{1f45b}',fitzpatrick_scale:!1,category:"people"},handbag:{keywords:["fashion","accessory","accessories","shopping"],char:'\u{1f45c}',fitzpatrick_scale:!1,category:"people"},briefcase:{keywords:["business","documents","work","law","legal","job","career"],char:'\u{1f4bc}',fitzpatrick_scale:!1,category:"people"},eyeglasses:{keywords:["fashion","accessories","eyesight","nerdy","dork","geek"],char:'\u{1f453}',fitzpatrick_scale:!1,category:"people"},dark_sunglasses:{keywords:["face","cool","accessories"],char:'\u{1f576}',fitzpatrick_scale:!1,category:"people"},goggles:{keywords:["eyes","protection","safety"],char:'\u{1f97d}',fitzpatrick_scale:!1,category:"people"},ring:{keywords:["wedding","propose","marriage","valentines","diamond","fashion","jewelry","gem","engagement"],char:'\u{1f48d}',fitzpatrick_scale:!1,category:"people"},closed_umbrella:{keywords:["weather","rain","drizzle"],char:'\u{1f302}',fitzpatrick_scale:!1,category:"people"},dog:{keywords:["animal","friend","nature","woof","puppy","pet","faithful"],char:'\u{1f436}',fitzpatrick_scale:!1,category:"animals_and_nature"},cat:{keywords:["animal","meow","nature","pet","kitten"],char:'\u{1f431}',fitzpatrick_scale:!1,category:"animals_and_nature"},mouse:{keywords:["animal","nature","cheese_wedge","rodent"],char:'\u{1f42d}',fitzpatrick_scale:!1,category:"animals_and_nature"},hamster:{keywords:["animal","nature"],char:'\u{1f439}',fitzpatrick_scale:!1,category:"animals_and_nature"},rabbit:{keywords:["animal","nature","pet","spring","magic","bunny"],char:'\u{1f430}',fitzpatrick_scale:!1,category:"animals_and_nature"},fox_face:{keywords:["animal","nature","face"],char:'\u{1f98a}',fitzpatrick_scale:!1,category:"animals_and_nature"},bear:{keywords:["animal","nature","wild"],char:'\u{1f43b}',fitzpatrick_scale:!1,category:"animals_and_nature"},panda_face:{keywords:["animal","nature","panda"],char:'\u{1f43c}',fitzpatrick_scale:!1,category:"animals_and_nature"},koala:{keywords:["animal","nature"],char:'\u{1f428}',fitzpatrick_scale:!1,category:"animals_and_nature"},tiger:{keywords:["animal","cat","danger","wild","nature","roar"],char:'\u{1f42f}',fitzpatrick_scale:!1,category:"animals_and_nature"},lion:{keywords:["animal","nature"],char:'\u{1f981}',fitzpatrick_scale:!1,category:"animals_and_nature"},cow:{keywords:["beef","ox","animal","nature","moo","milk"],char:'\u{1f42e}',fitzpatrick_scale:!1,category:"animals_and_nature"},pig:{keywords:["animal","oink","nature"],char:'\u{1f437}',fitzpatrick_scale:!1,category:"animals_and_nature"},pig_nose:{keywords:["animal","oink"],char:'\u{1f43d}',fitzpatrick_scale:!1,category:"animals_and_nature"},frog:{keywords:["animal","nature","croak","toad"],char:'\u{1f438}',fitzpatrick_scale:!1,category:"animals_and_nature"},squid:{keywords:["animal","nature","ocean","sea"],char:'\u{1f991}',fitzpatrick_scale:!1,category:"animals_and_nature"},octopus:{keywords:["animal","creature","ocean","sea","nature","beach"],char:'\u{1f419}',fitzpatrick_scale:!1,category:"animals_and_nature"},shrimp:{keywords:["animal","ocean","nature","seafood"],char:'\u{1f990}',fitzpatrick_scale:!1,category:"animals_and_nature"},monkey_face:{keywords:["animal","nature","circus"],char:'\u{1f435}',fitzpatrick_scale:!1,category:"animals_and_nature"},gorilla:{keywords:["animal","nature","circus"],char:'\u{1f98d}',fitzpatrick_scale:!1,category:"animals_and_nature"},see_no_evil:{keywords:["monkey","animal","nature","haha"],char:'\u{1f648}',fitzpatrick_scale:!1,category:"animals_and_nature"},hear_no_evil:{keywords:["animal","monkey","nature"],char:'\u{1f649}',fitzpatrick_scale:!1,category:"animals_and_nature"},speak_no_evil:{keywords:["monkey","animal","nature","omg"],char:'\u{1f64a}',fitzpatrick_scale:!1,category:"animals_and_nature"},monkey:{keywords:["animal","nature","banana","circus"],char:'\u{1f412}',fitzpatrick_scale:!1,category:"animals_and_nature"},chicken:{keywords:["animal","cluck","nature","bird"],char:'\u{1f414}',fitzpatrick_scale:!1,category:"animals_and_nature"},penguin:{keywords:["animal","nature"],char:'\u{1f427}',fitzpatrick_scale:!1,category:"animals_and_nature"},bird:{keywords:["animal","nature","fly","tweet","spring"],char:'\u{1f426}',fitzpatrick_scale:!1,category:"animals_and_nature"},baby_chick:{keywords:["animal","chicken","bird"],char:'\u{1f424}',fitzpatrick_scale:!1,category:"animals_and_nature"},hatching_chick:{keywords:["animal","chicken","egg","born","baby","bird"],char:'\u{1f423}',fitzpatrick_scale:!1,category:"animals_and_nature"},hatched_chick:{keywords:["animal","chicken","baby","bird"],char:'\u{1f425}',fitzpatrick_scale:!1,category:"animals_and_nature"},duck:{keywords:["animal","nature","bird","mallard"],char:'\u{1f986}',fitzpatrick_scale:!1,category:"animals_and_nature"},eagle:{keywords:["animal","nature","bird"],char:'\u{1f985}',fitzpatrick_scale:!1,category:"animals_and_nature"},owl:{keywords:["animal","nature","bird","hoot"],char:'\u{1f989}',fitzpatrick_scale:!1,category:"animals_and_nature"},bat:{keywords:["animal","nature","blind","vampire"],char:'\u{1f987}',fitzpatrick_scale:!1,category:"animals_and_nature"},wolf:{keywords:["animal","nature","wild"],char:'\u{1f43a}',fitzpatrick_scale:!1,category:"animals_and_nature"},boar:{keywords:["animal","nature"],char:'\u{1f417}',fitzpatrick_scale:!1,category:"animals_and_nature"},horse:{keywords:["animal","brown","nature"],char:'\u{1f434}',fitzpatrick_scale:!1,category:"animals_and_nature"},unicorn:{keywords:["animal","nature","mystical"],char:'\u{1f984}',fitzpatrick_scale:!1,category:"animals_and_nature"},honeybee:{keywords:["animal","insect","nature","bug","spring","honey"],char:'\u{1f41d}',fitzpatrick_scale:!1,category:"animals_and_nature"},bug:{keywords:["animal","insect","nature","worm"],char:'\u{1f41b}',fitzpatrick_scale:!1,category:"animals_and_nature"},butterfly:{keywords:["animal","insect","nature","caterpillar"],char:'\u{1f98b}',fitzpatrick_scale:!1,category:"animals_and_nature"},snail:{keywords:["slow","animal","shell"],char:'\u{1f40c}',fitzpatrick_scale:!1,category:"animals_and_nature"},beetle:{keywords:["animal","insect","nature","ladybug"],char:'\u{1f41e}',fitzpatrick_scale:!1,category:"animals_and_nature"},ant:{keywords:["animal","insect","nature","bug"],char:'\u{1f41c}',fitzpatrick_scale:!1,category:"animals_and_nature"},grasshopper:{keywords:["animal","cricket","chirp"],char:'\u{1f997}',fitzpatrick_scale:!1,category:"animals_and_nature"},spider:{keywords:["animal","arachnid"],char:'\u{1f577}',fitzpatrick_scale:!1,category:"animals_and_nature"},scorpion:{keywords:["animal","arachnid"],char:'\u{1f982}',fitzpatrick_scale:!1,category:"animals_and_nature"},crab:{keywords:["animal","crustacean"],char:'\u{1f980}',fitzpatrick_scale:!1,category:"animals_and_nature"},snake:{keywords:["animal","evil","nature","hiss","python"],char:'\u{1f40d}',fitzpatrick_scale:!1,category:"animals_and_nature"},lizard:{keywords:["animal","nature","reptile"],char:'\u{1f98e}',fitzpatrick_scale:!1,category:"animals_and_nature"},"t-rex":{keywords:["animal","nature","dinosaur","tyrannosaurus","extinct"],char:'\u{1f996}',fitzpatrick_scale:!1,category:"animals_and_nature"},sauropod:{keywords:["animal","nature","dinosaur","brachiosaurus","brontosaurus","diplodocus","extinct"],char:'\u{1f995}',fitzpatrick_scale:!1,category:"animals_and_nature"},turtle:{keywords:["animal","slow","nature","tortoise"],char:'\u{1f422}',fitzpatrick_scale:!1,category:"animals_and_nature"},tropical_fish:{keywords:["animal","swim","ocean","beach","nemo"],char:'\u{1f420}',fitzpatrick_scale:!1,category:"animals_and_nature"},fish:{keywords:["animal","food","nature"],char:'\u{1f41f}',fitzpatrick_scale:!1,category:"animals_and_nature"},blowfish:{keywords:["animal","nature","food","sea","ocean"],char:'\u{1f421}',fitzpatrick_scale:!1,category:"animals_and_nature"},dolphin:{keywords:["animal","nature","fish","sea","ocean","flipper","fins","beach"],char:'\u{1f42c}',fitzpatrick_scale:!1,category:"animals_and_nature"},shark:{keywords:["animal","nature","fish","sea","ocean","jaws","fins","beach"],char:'\u{1f988}',fitzpatrick_scale:!1,category:"animals_and_nature"},whale:{keywords:["animal","nature","sea","ocean"],char:'\u{1f433}',fitzpatrick_scale:!1,category:"animals_and_nature"},whale2:{keywords:["animal","nature","sea","ocean"],char:'\u{1f40b}',fitzpatrick_scale:!1,category:"animals_and_nature"},crocodile:{keywords:["animal","nature","reptile","lizard","alligator"],char:'\u{1f40a}',fitzpatrick_scale:!1,category:"animals_and_nature"},leopard:{keywords:["animal","nature"],char:'\u{1f406}',fitzpatrick_scale:!1,category:"animals_and_nature"},zebra:{keywords:["animal","nature","stripes","safari"],char:'\u{1f993}',fitzpatrick_scale:!1,category:"animals_and_nature"},tiger2:{keywords:["animal","nature","roar"],char:'\u{1f405}',fitzpatrick_scale:!1,category:"animals_and_nature"},water_buffalo:{keywords:["animal","nature","ox","cow"],char:'\u{1f403}',fitzpatrick_scale:!1,category:"animals_and_nature"},ox:{keywords:["animal","cow","beef"],char:'\u{1f402}',fitzpatrick_scale:!1,category:"animals_and_nature"},cow2:{keywords:["beef","ox","animal","nature","moo","milk"],char:'\u{1f404}',fitzpatrick_scale:!1,category:"animals_and_nature"},deer:{keywords:["animal","nature","horns","venison"],char:'\u{1f98c}',fitzpatrick_scale:!1,category:"animals_and_nature"},dromedary_camel:{keywords:["animal","hot","desert","hump"],char:'\u{1f42a}',fitzpatrick_scale:!1,category:"animals_and_nature"},camel:{keywords:["animal","nature","hot","desert","hump"],char:'\u{1f42b}',fitzpatrick_scale:!1,category:"animals_and_nature"},giraffe:{keywords:["animal","nature","spots","safari"],char:'\u{1f992}',fitzpatrick_scale:!1,category:"animals_and_nature"},elephant:{keywords:["animal","nature","nose","th","circus"],char:'\u{1f418}',fitzpatrick_scale:!1,category:"animals_and_nature"},rhinoceros:{keywords:["animal","nature","horn"],char:'\u{1f98f}',fitzpatrick_scale:!1,category:"animals_and_nature"},goat:{keywords:["animal","nature"],char:'\u{1f410}',fitzpatrick_scale:!1,category:"animals_and_nature"},ram:{keywords:["animal","sheep","nature"],char:'\u{1f40f}',fitzpatrick_scale:!1,category:"animals_and_nature"},sheep:{keywords:["animal","nature","wool","shipit"],char:'\u{1f411}',fitzpatrick_scale:!1,category:"animals_and_nature"},racehorse:{keywords:["animal","gamble","luck"],char:'\u{1f40e}',fitzpatrick_scale:!1,category:"animals_and_nature"},pig2:{keywords:["animal","nature"],char:'\u{1f416}',fitzpatrick_scale:!1,category:"animals_and_nature"},rat:{keywords:["animal","mouse","rodent"],char:'\u{1f400}',fitzpatrick_scale:!1,category:"animals_and_nature"},mouse2:{keywords:["animal","nature","rodent"],char:'\u{1f401}',fitzpatrick_scale:!1,category:"animals_and_nature"},rooster:{keywords:["animal","nature","chicken"],char:'\u{1f413}',fitzpatrick_scale:!1,category:"animals_and_nature"},turkey:{keywords:["animal","bird"],char:'\u{1f983}',fitzpatrick_scale:!1,category:"animals_and_nature"},dove:{keywords:["animal","bird"],char:'\u{1f54a}',fitzpatrick_scale:!1,category:"animals_and_nature"},dog2:{keywords:["animal","nature","friend","doge","pet","faithful"],char:'\u{1f415}',fitzpatrick_scale:!1,category:"animals_and_nature"},poodle:{keywords:["dog","animal","101","nature","pet"],char:'\u{1f429}',fitzpatrick_scale:!1,category:"animals_and_nature"},cat2:{keywords:["animal","meow","pet","cats"],char:'\u{1f408}',fitzpatrick_scale:!1,category:"animals_and_nature"},rabbit2:{keywords:["animal","nature","pet","magic","spring"],char:'\u{1f407}',fitzpatrick_scale:!1,category:"animals_and_nature"},chipmunk:{keywords:["animal","nature","rodent","squirrel"],char:'\u{1f43f}',fitzpatrick_scale:!1,category:"animals_and_nature"},hedgehog:{keywords:["animal","nature","spiny"],char:'\u{1f994}',fitzpatrick_scale:!1,category:"animals_and_nature"},raccoon:{keywords:["animal","nature"],char:'\u{1f99d}',fitzpatrick_scale:!1,category:"animals_and_nature"},llama:{keywords:["animal","nature","alpaca"],char:'\u{1f999}',fitzpatrick_scale:!1,category:"animals_and_nature"},hippopotamus:{keywords:["animal","nature"],char:'\u{1f99b}',fitzpatrick_scale:!1,category:"animals_and_nature"},kangaroo:{keywords:["animal","nature","australia","joey","hop","marsupial"],char:'\u{1f998}',fitzpatrick_scale:!1,category:"animals_and_nature"},badger:{keywords:["animal","nature","honey"],char:'\u{1f9a1}',fitzpatrick_scale:!1,category:"animals_and_nature"},swan:{keywords:["animal","nature","bird"],char:'\u{1f9a2}',fitzpatrick_scale:!1,category:"animals_and_nature"},peacock:{keywords:["animal","nature","peahen","bird"],char:'\u{1f99a}',fitzpatrick_scale:!1,category:"animals_and_nature"},parrot:{keywords:["animal","nature","bird","pirate","talk"],char:'\u{1f99c}',fitzpatrick_scale:!1,category:"animals_and_nature"},lobster:{keywords:["animal","nature","bisque","claws","seafood"],char:'\u{1f99e}',fitzpatrick_scale:!1,category:"animals_and_nature"},mosquito:{keywords:["animal","nature","insect","malaria"],char:'\u{1f99f}',fitzpatrick_scale:!1,category:"animals_and_nature"},paw_prints:{keywords:["animal","tracking","footprints","dog","cat","pet","feet"],char:'\u{1f43e}',fitzpatrick_scale:!1,category:"animals_and_nature"},dragon:{keywords:["animal","myth","nature","chinese","green"],char:'\u{1f409}',fitzpatrick_scale:!1,category:"animals_and_nature"},dragon_face:{keywords:["animal","myth","nature","chinese","green"],char:'\u{1f432}',fitzpatrick_scale:!1,category:"animals_and_nature"},cactus:{keywords:["vegetable","plant","nature"],char:'\u{1f335}',fitzpatrick_scale:!1,category:"animals_and_nature"},christmas_tree:{keywords:["festival","vacation","december","xmas","celebration"],char:'\u{1f384}',fitzpatrick_scale:!1,category:"animals_and_nature"},evergreen_tree:{keywords:["plant","nature"],char:'\u{1f332}',fitzpatrick_scale:!1,category:"animals_and_nature"},deciduous_tree:{keywords:["plant","nature"],char:'\u{1f333}',fitzpatrick_scale:!1,category:"animals_and_nature"},palm_tree:{keywords:["plant","vegetable","nature","summer","beach","mojito","tropical"],char:'\u{1f334}',fitzpatrick_scale:!1,category:"animals_and_nature"},seedling:{keywords:["plant","nature","grass","lawn","spring"],char:'\u{1f331}',fitzpatrick_scale:!1,category:"animals_and_nature"},herb:{keywords:["vegetable","plant","medicine","weed","grass","lawn"],char:'\u{1f33f}',fitzpatrick_scale:!1,category:"animals_and_nature"},shamrock:{keywords:["vegetable","plant","nature","irish","clover"],char:'\u2618',fitzpatrick_scale:!1,category:"animals_and_nature"},four_leaf_clover:{keywords:["vegetable","plant","nature","lucky","irish"],char:'\u{1f340}',fitzpatrick_scale:!1,category:"animals_and_nature"},bamboo:{keywords:["plant","nature","vegetable","panda","pine_decoration"],char:'\u{1f38d}',fitzpatrick_scale:!1,category:"animals_and_nature"},tanabata_tree:{keywords:["plant","nature","branch","summer"],char:'\u{1f38b}',fitzpatrick_scale:!1,category:"animals_and_nature"},leaves:{keywords:["nature","plant","tree","vegetable","grass","lawn","spring"],char:'\u{1f343}',fitzpatrick_scale:!1,category:"animals_and_nature"},fallen_leaf:{keywords:["nature","plant","vegetable","leaves"],char:'\u{1f342}',fitzpatrick_scale:!1,category:"animals_and_nature"},maple_leaf:{keywords:["nature","plant","vegetable","ca","fall"],char:'\u{1f341}',fitzpatrick_scale:!1,category:"animals_and_nature"},ear_of_rice:{keywords:["nature","plant"],char:'\u{1f33e}',fitzpatrick_scale:!1,category:"animals_and_nature"},hibiscus:{keywords:["plant","vegetable","flowers","beach"],char:'\u{1f33a}',fitzpatrick_scale:!1,category:"animals_and_nature"},sunflower:{keywords:["nature","plant","fall"],char:'\u{1f33b}',fitzpatrick_scale:!1,category:"animals_and_nature"},rose:{keywords:["flowers","valentines","love","spring"],char:'\u{1f339}',fitzpatrick_scale:!1,category:"animals_and_nature"},wilted_flower:{keywords:["plant","nature","flower"],char:'\u{1f940}',fitzpatrick_scale:!1,category:"animals_and_nature"},tulip:{keywords:["flowers","plant","nature","summer","spring"],char:'\u{1f337}',fitzpatrick_scale:!1,category:"animals_and_nature"},blossom:{keywords:["nature","flowers","yellow"],char:'\u{1f33c}',fitzpatrick_scale:!1,category:"animals_and_nature"},cherry_blossom:{keywords:["nature","plant","spring","flower"],char:'\u{1f338}',fitzpatrick_scale:!1,category:"animals_and_nature"},bouquet:{keywords:["flowers","nature","spring"],char:'\u{1f490}',fitzpatrick_scale:!1,category:"animals_and_nature"},mushroom:{keywords:["plant","vegetable"],char:'\u{1f344}',fitzpatrick_scale:!1,category:"animals_and_nature"},chestnut:{keywords:["food","squirrel"],char:'\u{1f330}',fitzpatrick_scale:!1,category:"animals_and_nature"},jack_o_lantern:{keywords:["halloween","light","pumpkin","creepy","fall"],char:'\u{1f383}',fitzpatrick_scale:!1,category:"animals_and_nature"},shell:{keywords:["nature","sea","beach"],char:'\u{1f41a}',fitzpatrick_scale:!1,category:"animals_and_nature"},spider_web:{keywords:["animal","insect","arachnid","silk"],char:'\u{1f578}',fitzpatrick_scale:!1,category:"animals_and_nature"},earth_americas:{keywords:["globe","world","USA","international"],char:'\u{1f30e}',fitzpatrick_scale:!1,category:"animals_and_nature"},earth_africa:{keywords:["globe","world","international"],char:'\u{1f30d}',fitzpatrick_scale:!1,category:"animals_and_nature"},earth_asia:{keywords:["globe","world","east","international"],char:'\u{1f30f}',fitzpatrick_scale:!1,category:"animals_and_nature"},full_moon:{keywords:["nature","yellow","twilight","planet","space","night","evening","sleep"],char:'\u{1f315}',fitzpatrick_scale:!1,category:"animals_and_nature"},waning_gibbous_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep","waxing_gibbous_moon"],char:'\u{1f316}',fitzpatrick_scale:!1,category:"animals_and_nature"},last_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f317}',fitzpatrick_scale:!1,category:"animals_and_nature"},waning_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f318}',fitzpatrick_scale:!1,category:"animals_and_nature"},new_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f311}',fitzpatrick_scale:!1,category:"animals_and_nature"},waxing_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f312}',fitzpatrick_scale:!1,category:"animals_and_nature"},first_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f313}',fitzpatrick_scale:!1,category:"animals_and_nature"},waxing_gibbous_moon:{keywords:["nature","night","sky","gray","twilight","planet","space","evening","sleep"],char:'\u{1f314}',fitzpatrick_scale:!1,category:"animals_and_nature"},new_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f31a}',fitzpatrick_scale:!1,category:"animals_and_nature"},full_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f31d}',fitzpatrick_scale:!1,category:"animals_and_nature"},first_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f31b}',fitzpatrick_scale:!1,category:"animals_and_nature"},last_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:'\u{1f31c}',fitzpatrick_scale:!1,category:"animals_and_nature"},sun_with_face:{keywords:["nature","morning","sky"],char:'\u{1f31e}',fitzpatrick_scale:!1,category:"animals_and_nature"},crescent_moon:{keywords:["night","sleep","sky","evening","magic"],char:'\u{1f319}',fitzpatrick_scale:!1,category:"animals_and_nature"},star:{keywords:["night","yellow"],char:'\u2b50',fitzpatrick_scale:!1,category:"animals_and_nature"},star2:{keywords:["night","sparkle","awesome","good","magic"],char:'\u{1f31f}',fitzpatrick_scale:!1,category:"animals_and_nature"},dizzy:{keywords:["star","sparkle","shoot","magic"],char:'\u{1f4ab}',fitzpatrick_scale:!1,category:"animals_and_nature"},sparkles:{keywords:["stars","shine","shiny","cool","awesome","good","magic"],char:'\u2728',fitzpatrick_scale:!1,category:"animals_and_nature"},comet:{keywords:["space"],char:'\u2604',fitzpatrick_scale:!1,category:"animals_and_nature"},sunny:{keywords:["weather","nature","brightness","summer","beach","spring"],char:'\u2600\ufe0f',fitzpatrick_scale:!1,category:"animals_and_nature"},sun_behind_small_cloud:{keywords:["weather"],char:'\u{1f324}',fitzpatrick_scale:!1,category:"animals_and_nature"},partly_sunny:{keywords:["weather","nature","cloudy","morning","fall","spring"],char:'\u26c5',fitzpatrick_scale:!1,category:"animals_and_nature"},sun_behind_large_cloud:{keywords:["weather"],char:'\u{1f325}',fitzpatrick_scale:!1,category:"animals_and_nature"},sun_behind_rain_cloud:{keywords:["weather"],char:'\u{1f326}',fitzpatrick_scale:!1,category:"animals_and_nature"},cloud:{keywords:["weather","sky"],char:'\u2601\ufe0f',fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_rain:{keywords:["weather"],char:'\u{1f327}',fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_lightning_and_rain:{keywords:["weather","lightning"],char:'\u26c8',fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_lightning:{keywords:["weather","thunder"],char:'\u{1f329}',fitzpatrick_scale:!1,category:"animals_and_nature"},zap:{keywords:["thunder","weather","lightning bolt","fast"],char:'\u26a1',fitzpatrick_scale:!1,category:"animals_and_nature"},fire:{keywords:["hot","cook","flame"],char:'\u{1f525}',fitzpatrick_scale:!1,category:"animals_and_nature"},boom:{keywords:["bomb","explode","explosion","collision","blown"],char:'\u{1f4a5}',fitzpatrick_scale:!1,category:"animals_and_nature"},snowflake:{keywords:["winter","season","cold","weather","christmas","xmas"],char:'\u2744\ufe0f',fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_snow:{keywords:["weather"],char:'\u{1f328}',fitzpatrick_scale:!1,category:"animals_and_nature"},snowman:{keywords:["winter","season","cold","weather","christmas","xmas","frozen","without_snow"],char:'\u26c4',fitzpatrick_scale:!1,category:"animals_and_nature"},snowman_with_snow:{keywords:["winter","season","cold","weather","christmas","xmas","frozen"],char:'\u2603',fitzpatrick_scale:!1,category:"animals_and_nature"},wind_face:{keywords:["gust","air"],char:'\u{1f32c}',fitzpatrick_scale:!1,category:"animals_and_nature"},dash:{keywords:["wind","air","fast","shoo","fart","smoke","puff"],char:'\u{1f4a8}',fitzpatrick_scale:!1,category:"animals_and_nature"},tornado:{keywords:["weather","cyclone","twister"],char:'\u{1f32a}',fitzpatrick_scale:!1,category:"animals_and_nature"},fog:{keywords:["weather"],char:'\u{1f32b}',fitzpatrick_scale:!1,category:"animals_and_nature"},open_umbrella:{keywords:["weather","spring"],char:'\u2602',fitzpatrick_scale:!1,category:"animals_and_nature"},umbrella:{keywords:["rainy","weather","spring"],char:'\u2614',fitzpatrick_scale:!1,category:"animals_and_nature"},droplet:{keywords:["water","drip","faucet","spring"],char:'\u{1f4a7}',fitzpatrick_scale:!1,category:"animals_and_nature"},sweat_drops:{keywords:["water","drip","oops"],char:'\u{1f4a6}',fitzpatrick_scale:!1,category:"animals_and_nature"},ocean:{keywords:["sea","water","wave","nature","tsunami","disaster"],char:'\u{1f30a}',fitzpatrick_scale:!1,category:"animals_and_nature"},green_apple:{keywords:["fruit","nature"],char:'\u{1f34f}',fitzpatrick_scale:!1,category:"food_and_drink"},apple:{keywords:["fruit","mac","school"],char:'\u{1f34e}',fitzpatrick_scale:!1,category:"food_and_drink"},pear:{keywords:["fruit","nature","food"],char:'\u{1f350}',fitzpatrick_scale:!1,category:"food_and_drink"},tangerine:{keywords:["food","fruit","nature","orange"],char:'\u{1f34a}',fitzpatrick_scale:!1,category:"food_and_drink"},lemon:{keywords:["fruit","nature"],char:'\u{1f34b}',fitzpatrick_scale:!1,category:"food_and_drink"},banana:{keywords:["fruit","food","monkey"],char:'\u{1f34c}',fitzpatrick_scale:!1,category:"food_and_drink"},watermelon:{keywords:["fruit","food","picnic","summer"],char:'\u{1f349}',fitzpatrick_scale:!1,category:"food_and_drink"},grapes:{keywords:["fruit","food","wine"],char:'\u{1f347}',fitzpatrick_scale:!1,category:"food_and_drink"},strawberry:{keywords:["fruit","food","nature"],char:'\u{1f353}',fitzpatrick_scale:!1,category:"food_and_drink"},melon:{keywords:["fruit","nature","food"],char:'\u{1f348}',fitzpatrick_scale:!1,category:"food_and_drink"},cherries:{keywords:["food","fruit"],char:'\u{1f352}',fitzpatrick_scale:!1,category:"food_and_drink"},peach:{keywords:["fruit","nature","food"],char:'\u{1f351}',fitzpatrick_scale:!1,category:"food_and_drink"},pineapple:{keywords:["fruit","nature","food"],char:'\u{1f34d}',fitzpatrick_scale:!1,category:"food_and_drink"},coconut:{keywords:["fruit","nature","food","palm"],char:'\u{1f965}',fitzpatrick_scale:!1,category:"food_and_drink"},kiwi_fruit:{keywords:["fruit","food"],char:'\u{1f95d}',fitzpatrick_scale:!1,category:"food_and_drink"},mango:{keywords:["fruit","food","tropical"],char:'\u{1f96d}',fitzpatrick_scale:!1,category:"food_and_drink"},avocado:{keywords:["fruit","food"],char:'\u{1f951}',fitzpatrick_scale:!1,category:"food_and_drink"},broccoli:{keywords:["fruit","food","vegetable"],char:'\u{1f966}',fitzpatrick_scale:!1,category:"food_and_drink"},tomato:{keywords:["fruit","vegetable","nature","food"],char:'\u{1f345}',fitzpatrick_scale:!1,category:"food_and_drink"},eggplant:{keywords:["vegetable","nature","food","aubergine"],char:'\u{1f346}',fitzpatrick_scale:!1,category:"food_and_drink"},cucumber:{keywords:["fruit","food","pickle"],char:'\u{1f952}',fitzpatrick_scale:!1,category:"food_and_drink"},carrot:{keywords:["vegetable","food","orange"],char:'\u{1f955}',fitzpatrick_scale:!1,category:"food_and_drink"},hot_pepper:{keywords:["food","spicy","chilli","chili"],char:'\u{1f336}',fitzpatrick_scale:!1,category:"food_and_drink"},potato:{keywords:["food","tuber","vegatable","starch"],char:'\u{1f954}',fitzpatrick_scale:!1,category:"food_and_drink"},corn:{keywords:["food","vegetable","plant"],char:'\u{1f33d}',fitzpatrick_scale:!1,category:"food_and_drink"},leafy_greens:{keywords:["food","vegetable","plant","bok choy","cabbage","kale","lettuce"],char:'\u{1f96c}',fitzpatrick_scale:!1,category:"food_and_drink"},sweet_potato:{keywords:["food","nature"],char:'\u{1f360}',fitzpatrick_scale:!1,category:"food_and_drink"},peanuts:{keywords:["food","nut"],char:'\u{1f95c}',fitzpatrick_scale:!1,category:"food_and_drink"},honey_pot:{keywords:["bees","sweet","kitchen"],char:'\u{1f36f}',fitzpatrick_scale:!1,category:"food_and_drink"},croissant:{keywords:["food","bread","french"],char:'\u{1f950}',fitzpatrick_scale:!1,category:"food_and_drink"},bread:{keywords:["food","wheat","breakfast","toast"],char:'\u{1f35e}',fitzpatrick_scale:!1,category:"food_and_drink"},baguette_bread:{keywords:["food","bread","french"],char:'\u{1f956}',fitzpatrick_scale:!1,category:"food_and_drink"},bagel:{keywords:["food","bread","bakery","schmear"],char:'\u{1f96f}',fitzpatrick_scale:!1,category:"food_and_drink"},pretzel:{keywords:["food","bread","twisted"],char:'\u{1f968}',fitzpatrick_scale:!1,category:"food_and_drink"},cheese:{keywords:["food","chadder"],char:'\u{1f9c0}',fitzpatrick_scale:!1,category:"food_and_drink"},egg:{keywords:["food","chicken","breakfast"],char:'\u{1f95a}',fitzpatrick_scale:!1,category:"food_and_drink"},bacon:{keywords:["food","breakfast","pork","pig","meat"],char:'\u{1f953}',fitzpatrick_scale:!1,category:"food_and_drink"},steak:{keywords:["food","cow","meat","cut","chop","lambchop","porkchop"],char:'\u{1f969}',fitzpatrick_scale:!1,category:"food_and_drink"},pancakes:{keywords:["food","breakfast","flapjacks","hotcakes"],char:'\u{1f95e}',fitzpatrick_scale:!1,category:"food_and_drink"},poultry_leg:{keywords:["food","meat","drumstick","bird","chicken","turkey"],char:'\u{1f357}',fitzpatrick_scale:!1,category:"food_and_drink"},meat_on_bone:{keywords:["good","food","drumstick"],char:'\u{1f356}',fitzpatrick_scale:!1,category:"food_and_drink"},bone:{keywords:["skeleton"],char:'\u{1f9b4}',fitzpatrick_scale:!1,category:"food_and_drink"},fried_shrimp:{keywords:["food","animal","appetizer","summer"],char:'\u{1f364}',fitzpatrick_scale:!1,category:"food_and_drink"},fried_egg:{keywords:["food","breakfast","kitchen","egg"],char:'\u{1f373}',fitzpatrick_scale:!1,category:"food_and_drink"},hamburger:{keywords:["meat","fast food","beef","cheeseburger","mcdonalds","burger king"],char:'\u{1f354}',fitzpatrick_scale:!1,category:"food_and_drink"},fries:{keywords:["chips","snack","fast food"],char:'\u{1f35f}',fitzpatrick_scale:!1,category:"food_and_drink"},stuffed_flatbread:{keywords:["food","flatbread","stuffed","gyro"],char:'\u{1f959}',fitzpatrick_scale:!1,category:"food_and_drink"},hotdog:{keywords:["food","frankfurter"],char:'\u{1f32d}',fitzpatrick_scale:!1,category:"food_and_drink"},pizza:{keywords:["food","party"],char:'\u{1f355}',fitzpatrick_scale:!1,category:"food_and_drink"},sandwich:{keywords:["food","lunch","bread"],char:'\u{1f96a}',fitzpatrick_scale:!1,category:"food_and_drink"},canned_food:{keywords:["food","soup"],char:'\u{1f96b}',fitzpatrick_scale:!1,category:"food_and_drink"},spaghetti:{keywords:["food","italian","noodle"],char:'\u{1f35d}',fitzpatrick_scale:!1,category:"food_and_drink"},taco:{keywords:["food","mexican"],char:'\u{1f32e}',fitzpatrick_scale:!1,category:"food_and_drink"},burrito:{keywords:["food","mexican"],char:'\u{1f32f}',fitzpatrick_scale:!1,category:"food_and_drink"},green_salad:{keywords:["food","healthy","lettuce"],char:'\u{1f957}',fitzpatrick_scale:!1,category:"food_and_drink"},shallow_pan_of_food:{keywords:["food","cooking","casserole","paella"],char:'\u{1f958}',fitzpatrick_scale:!1,category:"food_and_drink"},ramen:{keywords:["food","japanese","noodle","chopsticks"],char:'\u{1f35c}',fitzpatrick_scale:!1,category:"food_and_drink"},stew:{keywords:["food","meat","soup"],char:'\u{1f372}',fitzpatrick_scale:!1,category:"food_and_drink"},fish_cake:{keywords:["food","japan","sea","beach","narutomaki","pink","swirl","kamaboko","surimi","ramen"],char:'\u{1f365}',fitzpatrick_scale:!1,category:"food_and_drink"},fortune_cookie:{keywords:["food","prophecy"],char:'\u{1f960}',fitzpatrick_scale:!1,category:"food_and_drink"},sushi:{keywords:["food","fish","japanese","rice"],char:'\u{1f363}',fitzpatrick_scale:!1,category:"food_and_drink"},bento:{keywords:["food","japanese","box"],char:'\u{1f371}',fitzpatrick_scale:!1,category:"food_and_drink"},curry:{keywords:["food","spicy","hot","indian"],char:'\u{1f35b}',fitzpatrick_scale:!1,category:"food_and_drink"},rice_ball:{keywords:["food","japanese"],char:'\u{1f359}',fitzpatrick_scale:!1,category:"food_and_drink"},rice:{keywords:["food","china","asian"],char:'\u{1f35a}',fitzpatrick_scale:!1,category:"food_and_drink"},rice_cracker:{keywords:["food","japanese"],char:'\u{1f358}',fitzpatrick_scale:!1,category:"food_and_drink"},oden:{keywords:["food","japanese"],char:'\u{1f362}',fitzpatrick_scale:!1,category:"food_and_drink"},dango:{keywords:["food","dessert","sweet","japanese","barbecue","meat"],char:'\u{1f361}',fitzpatrick_scale:!1,category:"food_and_drink"},shaved_ice:{keywords:["hot","dessert","summer"],char:'\u{1f367}',fitzpatrick_scale:!1,category:"food_and_drink"},ice_cream:{keywords:["food","hot","dessert"],char:'\u{1f368}',fitzpatrick_scale:!1,category:"food_and_drink"},icecream:{keywords:["food","hot","dessert","summer"],char:'\u{1f366}',fitzpatrick_scale:!1,category:"food_and_drink"},pie:{keywords:["food","dessert","pastry"],char:'\u{1f967}',fitzpatrick_scale:!1,category:"food_and_drink"},cake:{keywords:["food","dessert"],char:'\u{1f370}',fitzpatrick_scale:!1,category:"food_and_drink"},cupcake:{keywords:["food","dessert","bakery","sweet"],char:'\u{1f9c1}',fitzpatrick_scale:!1,category:"food_and_drink"},moon_cake:{keywords:["food","autumn"],char:'\u{1f96e}',fitzpatrick_scale:!1,category:"food_and_drink"},birthday:{keywords:["food","dessert","cake"],char:'\u{1f382}',fitzpatrick_scale:!1,category:"food_and_drink"},custard:{keywords:["dessert","food"],char:'\u{1f36e}',fitzpatrick_scale:!1,category:"food_and_drink"},candy:{keywords:["snack","dessert","sweet","lolly"],char:'\u{1f36c}',fitzpatrick_scale:!1,category:"food_and_drink"},lollipop:{keywords:["food","snack","candy","sweet"],char:'\u{1f36d}',fitzpatrick_scale:!1,category:"food_and_drink"},chocolate_bar:{keywords:["food","snack","dessert","sweet"],char:'\u{1f36b}',fitzpatrick_scale:!1,category:"food_and_drink"},popcorn:{keywords:["food","movie theater","films","snack"],char:'\u{1f37f}',fitzpatrick_scale:!1,category:"food_and_drink"},dumpling:{keywords:["food","empanada","pierogi","potsticker"],char:'\u{1f95f}',fitzpatrick_scale:!1,category:"food_and_drink"},doughnut:{keywords:["food","dessert","snack","sweet","donut"],char:'\u{1f369}',fitzpatrick_scale:!1,category:"food_and_drink"},cookie:{keywords:["food","snack","oreo","chocolate","sweet","dessert"],char:'\u{1f36a}',fitzpatrick_scale:!1,category:"food_and_drink"},milk_glass:{keywords:["beverage","drink","cow"],char:'\u{1f95b}',fitzpatrick_scale:!1,category:"food_and_drink"},beer:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:'\u{1f37a}',fitzpatrick_scale:!1,category:"food_and_drink"},beers:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:'\u{1f37b}',fitzpatrick_scale:!1,category:"food_and_drink"},clinking_glasses:{keywords:["beverage","drink","party","alcohol","celebrate","cheers","wine","champagne","toast"],char:'\u{1f942}',fitzpatrick_scale:!1,category:"food_and_drink"},wine_glass:{keywords:["drink","beverage","drunk","alcohol","booze"],char:'\u{1f377}',fitzpatrick_scale:!1,category:"food_and_drink"},tumbler_glass:{keywords:["drink","beverage","drunk","alcohol","liquor","booze","bourbon","scotch","whisky","glass","shot"],char:'\u{1f943}',fitzpatrick_scale:!1,category:"food_and_drink"},cocktail:{keywords:["drink","drunk","alcohol","beverage","booze","mojito"],char:'\u{1f378}',fitzpatrick_scale:!1,category:"food_and_drink"},tropical_drink:{keywords:["beverage","cocktail","summer","beach","alcohol","booze","mojito"],char:'\u{1f379}',fitzpatrick_scale:!1,category:"food_and_drink"},champagne:{keywords:["drink","wine","bottle","celebration"],char:'\u{1f37e}',fitzpatrick_scale:!1,category:"food_and_drink"},sake:{keywords:["wine","drink","drunk","beverage","japanese","alcohol","booze"],char:'\u{1f376}',fitzpatrick_scale:!1,category:"food_and_drink"},tea:{keywords:["drink","bowl","breakfast","green","british"],char:'\u{1f375}',fitzpatrick_scale:!1,category:"food_and_drink"},cup_with_straw:{keywords:["drink","soda"],char:'\u{1f964}',fitzpatrick_scale:!1,category:"food_and_drink"},coffee:{keywords:["beverage","caffeine","latte","espresso"],char:'\u2615',fitzpatrick_scale:!1,category:"food_and_drink"},baby_bottle:{keywords:["food","container","milk"],char:'\u{1f37c}',fitzpatrick_scale:!1,category:"food_and_drink"},salt:{keywords:["condiment","shaker"],char:'\u{1f9c2}',fitzpatrick_scale:!1,category:"food_and_drink"},spoon:{keywords:["cutlery","kitchen","tableware"],char:'\u{1f944}',fitzpatrick_scale:!1,category:"food_and_drink"},fork_and_knife:{keywords:["cutlery","kitchen"],char:'\u{1f374}',fitzpatrick_scale:!1,category:"food_and_drink"},plate_with_cutlery:{keywords:["food","eat","meal","lunch","dinner","restaurant"],char:'\u{1f37d}',fitzpatrick_scale:!1,category:"food_and_drink"},bowl_with_spoon:{keywords:["food","breakfast","cereal","oatmeal","porridge"],char:'\u{1f963}',fitzpatrick_scale:!1,category:"food_and_drink"},takeout_box:{keywords:["food","leftovers"],char:'\u{1f961}',fitzpatrick_scale:!1,category:"food_and_drink"},chopsticks:{keywords:["food"],char:'\u{1f962}',fitzpatrick_scale:!1,category:"food_and_drink"},soccer:{keywords:["sports","football"],char:'\u26bd',fitzpatrick_scale:!1,category:"activity"},basketball:{keywords:["sports","balls","NBA"],char:'\u{1f3c0}',fitzpatrick_scale:!1,category:"activity"},football:{keywords:["sports","balls","NFL"],char:'\u{1f3c8}',fitzpatrick_scale:!1,category:"activity"},baseball:{keywords:["sports","balls"],char:'\u26be',fitzpatrick_scale:!1,category:"activity"},softball:{keywords:["sports","balls"],char:'\u{1f94e}',fitzpatrick_scale:!1,category:"activity"},tennis:{keywords:["sports","balls","green"],char:'\u{1f3be}',fitzpatrick_scale:!1,category:"activity"},volleyball:{keywords:["sports","balls"],char:'\u{1f3d0}',fitzpatrick_scale:!1,category:"activity"},rugby_football:{keywords:["sports","team"],char:'\u{1f3c9}',fitzpatrick_scale:!1,category:"activity"},flying_disc:{keywords:["sports","frisbee","ultimate"],char:'\u{1f94f}',fitzpatrick_scale:!1,category:"activity"},"8ball":{keywords:["pool","hobby","game","luck","magic"],char:'\u{1f3b1}',fitzpatrick_scale:!1,category:"activity"},golf:{keywords:["sports","business","flag","hole","summer"],char:'\u26f3',fitzpatrick_scale:!1,category:"activity"},golfing_woman:{keywords:["sports","business","woman","female"],char:'\u{1f3cc}\ufe0f\u200d\u2640\ufe0f',fitzpatrick_scale:!1,category:"activity"},golfing_man:{keywords:["sports","business"],char:'\u{1f3cc}',fitzpatrick_scale:!0,category:"activity"},ping_pong:{keywords:["sports","pingpong"],char:'\u{1f3d3}',fitzpatrick_scale:!1,category:"activity"},badminton:{keywords:["sports"],char:'\u{1f3f8}',fitzpatrick_scale:!1,category:"activity"},goal_net:{keywords:["sports"],char:'\u{1f945}',fitzpatrick_scale:!1,category:"activity"},ice_hockey:{keywords:["sports"],char:'\u{1f3d2}',fitzpatrick_scale:!1,category:"activity"},field_hockey:{keywords:["sports"],char:'\u{1f3d1}',fitzpatrick_scale:!1,category:"activity"},lacrosse:{keywords:["sports","ball","stick"],char:'\u{1f94d}',fitzpatrick_scale:!1,category:"activity"},cricket:{keywords:["sports"],char:'\u{1f3cf}',fitzpatrick_scale:!1,category:"activity"},ski:{keywords:["sports","winter","cold","snow"],char:'\u{1f3bf}',fitzpatrick_scale:!1,category:"activity"},skier:{keywords:["sports","winter","snow"],char:'\u26f7',fitzpatrick_scale:!1,category:"activity"},snowboarder:{keywords:["sports","winter"],char:'\u{1f3c2}',fitzpatrick_scale:!0,category:"activity"},person_fencing:{keywords:["sports","fencing","sword"],char:'\u{1f93a}',fitzpatrick_scale:!1,category:"activity"},women_wrestling:{keywords:["sports","wrestlers"],char:'\u{1f93c}\u200d\u2640\ufe0f',fitzpatrick_scale:!1,category:"activity"},men_wrestling:{keywords:["sports","wrestlers"],char:'\u{1f93c}\u200d\u2642\ufe0f',fitzpatrick_scale:!1,category:"activity"},woman_cartwheeling:{keywords:["gymnastics"],char:'\u{1f938}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},man_cartwheeling:{keywords:["gymnastics"],char:'\u{1f938}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},woman_playing_handball:{keywords:["sports"],char:'\u{1f93e}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},man_playing_handball:{keywords:["sports"],char:'\u{1f93e}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},ice_skate:{keywords:["sports"],char:'\u26f8',fitzpatrick_scale:!1,category:"activity"},curling_stone:{keywords:["sports"],char:'\u{1f94c}',fitzpatrick_scale:!1,category:"activity"},skateboard:{keywords:["board"],char:'\u{1f6f9}',fitzpatrick_scale:!1,category:"activity"},sled:{keywords:["sleigh","luge","toboggan"],char:'\u{1f6f7}',fitzpatrick_scale:!1,category:"activity"},bow_and_arrow:{keywords:["sports"],char:'\u{1f3f9}',fitzpatrick_scale:!1,category:"activity"},fishing_pole_and_fish:{keywords:["food","hobby","summer"],char:'\u{1f3a3}',fitzpatrick_scale:!1,category:"activity"},boxing_glove:{keywords:["sports","fighting"],char:'\u{1f94a}',fitzpatrick_scale:!1,category:"activity"},martial_arts_uniform:{keywords:["judo","karate","taekwondo"],char:'\u{1f94b}',fitzpatrick_scale:!1,category:"activity"},rowing_woman:{keywords:["sports","hobby","water","ship","woman","female"],char:'\u{1f6a3}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},rowing_man:{keywords:["sports","hobby","water","ship"],char:'\u{1f6a3}',fitzpatrick_scale:!0,category:"activity"},climbing_woman:{keywords:["sports","hobby","woman","female","rock"],char:'\u{1f9d7}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},climbing_man:{keywords:["sports","hobby","man","male","rock"],char:'\u{1f9d7}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},swimming_woman:{keywords:["sports","exercise","human","athlete","water","summer","woman","female"],char:'\u{1f3ca}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},swimming_man:{keywords:["sports","exercise","human","athlete","water","summer"],char:'\u{1f3ca}',fitzpatrick_scale:!0,category:"activity"},woman_playing_water_polo:{keywords:["sports","pool"],char:'\u{1f93d}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},man_playing_water_polo:{keywords:["sports","pool"],char:'\u{1f93d}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},woman_in_lotus_position:{keywords:["woman","female","meditation","yoga","serenity","zen","mindfulness"],char:'\u{1f9d8}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},man_in_lotus_position:{keywords:["man","male","meditation","yoga","serenity","zen","mindfulness"],char:'\u{1f9d8}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},surfing_woman:{keywords:["sports","ocean","sea","summer","beach","woman","female"],char:'\u{1f3c4}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},surfing_man:{keywords:["sports","ocean","sea","summer","beach"],char:'\u{1f3c4}',fitzpatrick_scale:!0,category:"activity"},bath:{keywords:["clean","shower","bathroom"],char:'\u{1f6c0}',fitzpatrick_scale:!0,category:"activity"},basketball_woman:{keywords:["sports","human","woman","female"],char:'\u26f9\ufe0f\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},basketball_man:{keywords:["sports","human"],char:'\u26f9',fitzpatrick_scale:!0,category:"activity"},weight_lifting_woman:{keywords:["sports","training","exercise","woman","female"],char:'\u{1f3cb}\ufe0f\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},weight_lifting_man:{keywords:["sports","training","exercise"],char:'\u{1f3cb}',fitzpatrick_scale:!0,category:"activity"},biking_woman:{keywords:["sports","bike","exercise","hipster","woman","female"],char:'\u{1f6b4}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},biking_man:{keywords:["sports","bike","exercise","hipster"],char:'\u{1f6b4}',fitzpatrick_scale:!0,category:"activity"},mountain_biking_woman:{keywords:["transportation","sports","human","race","bike","woman","female"],char:'\u{1f6b5}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},mountain_biking_man:{keywords:["transportation","sports","human","race","bike"],char:'\u{1f6b5}',fitzpatrick_scale:!0,category:"activity"},horse_racing:{keywords:["animal","betting","competition","gambling","luck"],char:'\u{1f3c7}',fitzpatrick_scale:!0,category:"activity"},business_suit_levitating:{keywords:["suit","business","levitate","hover","jump"],char:'\u{1f574}',fitzpatrick_scale:!0,category:"activity"},trophy:{keywords:["win","award","contest","place","ftw","ceremony"],char:'\u{1f3c6}',fitzpatrick_scale:!1,category:"activity"},running_shirt_with_sash:{keywords:["play","pageant"],char:'\u{1f3bd}',fitzpatrick_scale:!1,category:"activity"},medal_sports:{keywords:["award","winning"],char:'\u{1f3c5}',fitzpatrick_scale:!1,category:"activity"},medal_military:{keywords:["award","winning","army"],char:'\u{1f396}',fitzpatrick_scale:!1,category:"activity"},"1st_place_medal":{keywords:["award","winning","first"],char:'\u{1f947}',fitzpatrick_scale:!1,category:"activity"},"2nd_place_medal":{keywords:["award","second"],char:'\u{1f948}',fitzpatrick_scale:!1,category:"activity"},"3rd_place_medal":{keywords:["award","third"],char:'\u{1f949}',fitzpatrick_scale:!1,category:"activity"},reminder_ribbon:{keywords:["sports","cause","support","awareness"],char:'\u{1f397}',fitzpatrick_scale:!1,category:"activity"},rosette:{keywords:["flower","decoration","military"],char:'\u{1f3f5}',fitzpatrick_scale:!1,category:"activity"},ticket:{keywords:["event","concert","pass"],char:'\u{1f3ab}',fitzpatrick_scale:!1,category:"activity"},tickets:{keywords:["sports","concert","entrance"],char:'\u{1f39f}',fitzpatrick_scale:!1,category:"activity"},performing_arts:{keywords:["acting","theater","drama"],char:'\u{1f3ad}',fitzpatrick_scale:!1,category:"activity"},art:{keywords:["design","paint","draw","colors"],char:'\u{1f3a8}',fitzpatrick_scale:!1,category:"activity"},circus_tent:{keywords:["festival","carnival","party"],char:'\u{1f3aa}',fitzpatrick_scale:!1,category:"activity"},woman_juggling:{keywords:["juggle","balance","skill","multitask"],char:'\u{1f939}\u200d\u2640\ufe0f',fitzpatrick_scale:!0,category:"activity"},man_juggling:{keywords:["juggle","balance","skill","multitask"],char:'\u{1f939}\u200d\u2642\ufe0f',fitzpatrick_scale:!0,category:"activity"},microphone:{keywords:["sound","music","PA","sing","talkshow"],char:'\u{1f3a4}',fitzpatrick_scale:!1,category:"activity"},headphones:{keywords:["music","score","gadgets"],char:'\u{1f3a7}',fitzpatrick_scale:!1,category:"activity"},musical_score:{keywords:["treble","clef","compose"],char:'\u{1f3bc}',fitzpatrick_scale:!1,category:"activity"},musical_keyboard:{keywords:["piano","instrument","compose"],char:'\u{1f3b9}',fitzpatrick_scale:!1,category:"activity"},drum:{keywords:["music","instrument","drumsticks","snare"],char:'\u{1f941}',fitzpatrick_scale:!1,category:"activity"},saxophone:{keywords:["music","instrument","jazz","blues"],char:'\u{1f3b7}',fitzpatrick_scale:!1,category:"activity"},trumpet:{keywords:["music","brass"],char:'\u{1f3ba}',fitzpatrick_scale:!1,category:"activity"},guitar:{keywords:["music","instrument"],char:'\u{1f3b8}',fitzpatrick_scale:!1,category:"activity"},violin:{keywords:["music","instrument","orchestra","symphony"],char:'\u{1f3bb}',fitzpatrick_scale:!1,category:"activity"},clapper:{keywords:["movie","film","record"],char:'\u{1f3ac}',fitzpatrick_scale:!1,category:"activity"},video_game:{keywords:["play","console","PS4","controller"],char:'\u{1f3ae}',fitzpatrick_scale:!1,category:"activity"},space_invader:{keywords:["game","arcade","play"],char:'\u{1f47e}',fitzpatrick_scale:!1,category:"activity"},dart:{keywords:["game","play","bar","target","bullseye"],char:'\u{1f3af}',fitzpatrick_scale:!1,category:"activity"},game_die:{keywords:["dice","random","tabletop","play","luck"],char:'\u{1f3b2}',fitzpatrick_scale:!1,category:"activity"},chess_pawn:{keywords:["expendable"],char:"\u265f",fitzpatrick_scale:!1,category:"activity"},slot_machine:{keywords:["bet","gamble","vegas","fruit machine","luck","casino"],char:'\u{1f3b0}',fitzpatrick_scale:!1,category:"activity"},jigsaw:{keywords:["interlocking","puzzle","piece"],char:'\u{1f9e9}',fitzpatrick_scale:!1,category:"activity"},bowling:{keywords:["sports","fun","play"],char:'\u{1f3b3}',fitzpatrick_scale:!1,category:"activity"},red_car:{keywords:["red","transportation","vehicle"],char:'\u{1f697}',fitzpatrick_scale:!1,category:"travel_and_places"},taxi:{keywords:["uber","vehicle","cars","transportation"],char:'\u{1f695}',fitzpatrick_scale:!1,category:"travel_and_places"},blue_car:{keywords:["transportation","vehicle"],char:'\u{1f699}',fitzpatrick_scale:!1,category:"travel_and_places"},bus:{keywords:["car","vehicle","transportation"],char:'\u{1f68c}',fitzpatrick_scale:!1,category:"travel_and_places"},trolleybus:{keywords:["bart","transportation","vehicle"],char:'\u{1f68e}',fitzpatrick_scale:!1,category:"travel_and_places"},racing_car:{keywords:["sports","race","fast","formula","f1"],char:'\u{1f3ce}',fitzpatrick_scale:!1,category:"travel_and_places"},police_car:{keywords:["vehicle","cars","transportation","law","legal","enforcement"],char:'\u{1f693}',fitzpatrick_scale:!1,category:"travel_and_places"},ambulance:{keywords:["health","911","hospital"],char:'\u{1f691}',fitzpatrick_scale:!1,category:"travel_and_places"},fire_engine:{keywords:["transportation","cars","vehicle"],char:'\u{1f692}',fitzpatrick_scale:!1,category:"travel_and_places"},minibus:{keywords:["vehicle","car","transportation"],char:'\u{1f690}',fitzpatrick_scale:!1,category:"travel_and_places"},truck:{keywords:["cars","transportation"],char:'\u{1f69a}',fitzpatrick_scale:!1,category:"travel_and_places"},articulated_lorry:{keywords:["vehicle","cars","transportation","express"],char:'\u{1f69b}',fitzpatrick_scale:!1,category:"travel_and_places"},tractor:{keywords:["vehicle","car","farming","agriculture"],char:'\u{1f69c}',fitzpatrick_scale:!1,category:"travel_and_places"},kick_scooter:{keywords:["vehicle","kick","razor"],char:'\u{1f6f4}',fitzpatrick_scale:!1,category:"travel_and_places"},motorcycle:{keywords:["race","sports","fast"],char:'\u{1f3cd}',fitzpatrick_scale:!1,category:"travel_and_places"},bike:{keywords:["sports","bicycle","exercise","hipster"],char:'\u{1f6b2}',fitzpatrick_scale:!1,category:"travel_and_places"},motor_scooter:{keywords:["vehicle","vespa","sasha"],char:'\u{1f6f5}',fitzpatrick_scale:!1,category:"travel_and_places"},rotating_light:{keywords:["police","ambulance","911","emergency","alert","error","pinged","law","legal"],char:'\u{1f6a8}',fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_police_car:{keywords:["vehicle","law","legal","enforcement","911"],char:'\u{1f694}',fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_bus:{keywords:["vehicle","transportation"],char:'\u{1f68d}',fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_automobile:{keywords:["car","vehicle","transportation"],char:'\u{1f698}',fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_taxi:{keywords:["vehicle","cars","uber"],char:'\u{1f696}',fitzpatrick_scale:!1,category:"travel_and_places"},aerial_tramway:{keywords:["transportation","vehicle","ski"],char:'\u{1f6a1}',fitzpatrick_scale:!1,category:"travel_and_places"},mountain_cableway:{keywords:["transportation","vehicle","ski"],char:'\u{1f6a0}',fitzpatrick_scale:!1,category:"travel_and_places"},suspension_railway:{keywords:["vehicle","transportation"],char:'\u{1f69f}',fitzpatrick_scale:!1,category:"travel_and_places"},railway_car:{keywords:["transportation","vehicle"],char:'\u{1f683}',fitzpatrick_scale:!1,category:"travel_and_places"},train:{keywords:["transportation","vehicle","carriage","public","travel"],char:'\u{1f68b}',fitzpatrick_scale:!1,category:"travel_and_places"},monorail:{keywords:["transportation","vehicle"],char:'\u{1f69d}',fitzpatrick_scale:!1,category:"travel_and_places"},bullettrain_side:{keywords:["transportation","vehicle"],char:'\u{1f684}',fitzpatrick_scale:!1,category:"travel_and_places"},bullettrain_front:{keywords:["transportation","vehicle","speed","fast","public","travel"],char:'\u{1f685}',fitzpatrick_scale:!1,category:"travel_and_places"},light_rail:{keywords:["transportation","vehicle"],char:'\u{1f688}',fitzpatrick_scale:!1,category:"travel_and_places"},mountain_railway:{keywords:["transportation","vehicle"],char:'\u{1f69e}',fitzpatrick_scale:!1,category:"travel_and_places"},steam_locomotive:{keywords:["transportation","vehicle","train"],char:'\u{1f682}',fitzpatrick_scale:!1,category:"travel_and_places"},train2:{keywords:["transportation","vehicle"],char:'\u{1f686}',fitzpatrick_scale:!1,category:"travel_and_places"},metro:{keywords:["transportation","blue-square","mrt","underground","tube"],char:'\u{1f687}',fitzpatrick_scale:!1,category:"travel_and_places"},tram:{keywords:["transportation","vehicle"],char:'\u{1f68a}',fitzpatrick_scale:!1,category:"travel_and_places"},station:{keywords:["transportation","vehicle","public"],char:'\u{1f689}',fitzpatrick_scale:!1,category:"travel_and_places"},flying_saucer:{keywords:["transportation","vehicle","ufo"],char:'\u{1f6f8}',fitzpatrick_scale:!1,category:"travel_and_places"},helicopter:{keywords:["transportation","vehicle","fly"],char:'\u{1f681}',fitzpatrick_scale:!1,category:"travel_and_places"},small_airplane:{keywords:["flight","transportation","fly","vehicle"],char:'\u{1f6e9}',fitzpatrick_scale:!1,category:"travel_and_places"},airplane:{keywords:["vehicle","transportation","flight","fly"],char:'\u2708\ufe0f',fitzpatrick_scale:!1,category:"travel_and_places"},flight_departure:{keywords:["airport","flight","landing"],char:'\u{1f6eb}',fitzpatrick_scale:!1,category:"travel_and_places"},flight_arrival:{keywords:["airport","flight","boarding"],char:'\u{1f6ec}',fitzpatrick_scale:!1,category:"travel_and_places"},sailboat:{keywords:["ship","summer","transportation","water","sailing"],char:'\u26f5',fitzpatrick_scale:!1,category:"travel_and_places"},motor_boat:{keywords:["ship"],char:'\u{1f6e5}',fitzpatrick_scale:!1,category:"travel_and_places"},speedboat:{keywords:["ship","transportation","vehicle","summer"],char:'\u{1f6a4}',fitzpatrick_scale:!1,category:"travel_and_places"},ferry:{keywords:["boat","ship","yacht"],char:'\u26f4',fitzpatrick_scale:!1,category:"travel_and_places"},passenger_ship:{keywords:["yacht","cruise","ferry"],char:'\u{1f6f3}',fitzpatrick_scale:!1,category:"travel_and_places"},rocket:{keywords:["launch","ship","staffmode","NASA","outer space","outer_space","fly"],char:'\u{1f680}',fitzpatrick_scale:!1,category:"travel_and_places"},artificial_satellite:{keywords:["communication","gps","orbit","spaceflight","NASA","ISS"],char:'\u{1f6f0}',fitzpatrick_scale:!1,category:"travel_and_places"},seat:{keywords:["sit","airplane","transport","bus","flight","fly"],char:'\u{1f4ba}',fitzpatrick_scale:!1,category:"travel_and_places"},canoe:{keywords:["boat","paddle","water","ship"],char:'\u{1f6f6}',fitzpatrick_scale:!1,category:"travel_and_places"},anchor:{keywords:["ship","ferry","sea","boat"],char:'\u2693',fitzpatrick_scale:!1,category:"travel_and_places"},construction:{keywords:["wip","progress","caution","warning"],char:'\u{1f6a7}',fitzpatrick_scale:!1,category:"travel_and_places"},fuelpump:{keywords:["gas station","petroleum"],char:'\u26fd',fitzpatrick_scale:!1,category:"travel_and_places"},busstop:{keywords:["transportation","wait"],char:'\u{1f68f}',fitzpatrick_scale:!1,category:"travel_and_places"},vertical_traffic_light:{keywords:["transportation","driving"],char:'\u{1f6a6}',fitzpatrick_scale:!1,category:"travel_and_places"},traffic_light:{keywords:["transportation","signal"],char:'\u{1f6a5}',fitzpatrick_scale:!1,category:"travel_and_places"},checkered_flag:{keywords:["contest","finishline","race","gokart"],char:'\u{1f3c1}',fitzpatrick_scale:!1,category:"travel_and_places"},ship:{keywords:["transportation","titanic","deploy"],char:'\u{1f6a2}',fitzpatrick_scale:!1,category:"travel_and_places"},ferris_wheel:{keywords:["photo","carnival","londoneye"],char:'\u{1f3a1}',fitzpatrick_scale:!1,category:"travel_and_places"},roller_coaster:{keywords:["carnival","playground","photo","fun"],char:'\u{1f3a2}',fitzpatrick_scale:!1,category:"travel_and_places"},carousel_horse:{keywords:["photo","carnival"],char:'\u{1f3a0}',fitzpatrick_scale:!1,category:"travel_and_places"},building_construction:{keywords:["wip","working","progress"],char:'\u{1f3d7}',fitzpatrick_scale:!1,category:"travel_and_places"},foggy:{keywords:["photo","mountain"],char:'\u{1f301}',fitzpatrick_scale:!1,category:"travel_and_places"},tokyo_tower:{keywords:["photo","japanese"],char:'\u{1f5fc}',fitzpatrick_scale:!1,category:"travel_and_places"},factory:{keywords:["building","industry","pollution","smoke"],char:'\u{1f3ed}',fitzpatrick_scale:!1,category:"travel_and_places"},fountain:{keywords:["photo","summer","water","fresh"],char:'\u26f2',fitzpatrick_scale:!1,category:"travel_and_places"},rice_scene:{keywords:["photo","japan","asia","tsukimi"],char:'\u{1f391}',fitzpatrick_scale:!1,category:"travel_and_places"},mountain:{keywords:["photo","nature","environment"],char:'\u26f0',fitzpatrick_scale:!1,category:"travel_and_places"},mountain_snow:{keywords:["photo","nature","environment","winter","cold"],char:'\u{1f3d4}',fitzpatrick_scale:!1,category:"travel_and_places"},mount_fuji:{keywords:["photo","mountain","nature","japanese"],char:'\u{1f5fb}',fitzpatrick_scale:!1,category:"travel_and_places"},volcano:{keywords:["photo","nature","disaster"],char:'\u{1f30b}',fitzpatrick_scale:!1,category:"travel_and_places"},japan:{keywords:["nation","country","japanese","asia"],char:'\u{1f5fe}',fitzpatrick_scale:!1,category:"travel_and_places"},camping:{keywords:["photo","outdoors","tent"],char:'\u{1f3d5}',fitzpatrick_scale:!1,category:"travel_and_places"},tent:{keywords:["photo","camping","outdoors"],char:'\u26fa',fitzpatrick_scale:!1,category:"travel_and_places"},national_park:{keywords:["photo","environment","nature"],char:'\u{1f3de}',fitzpatrick_scale:!1,category:"travel_and_places"},motorway:{keywords:["road","cupertino","interstate","highway"],char:'\u{1f6e3}',fitzpatrick_scale:!1,category:"travel_and_places"},railway_track:{keywords:["train","transportation"],char:'\u{1f6e4}',fitzpatrick_scale:!1,category:"travel_and_places"},sunrise:{keywords:["morning","view","vacation","photo"],char:'\u{1f305}',fitzpatrick_scale:!1,category:"travel_and_places"},sunrise_over_mountains:{keywords:["view","vacation","photo"],char:'\u{1f304}',fitzpatrick_scale:!1,category:"travel_and_places"},desert:{keywords:["photo","warm","saharah"],char:'\u{1f3dc}',fitzpatrick_scale:!1,category:"travel_and_places"},beach_umbrella:{keywords:["weather","summer","sunny","sand","mojito"],char:'\u{1f3d6}',fitzpatrick_scale:!1,category:"travel_and_places"},desert_island:{keywords:["photo","tropical","mojito"],char:'\u{1f3dd}',fitzpatrick_scale:!1,category:"travel_and_places"},city_sunrise:{keywords:["photo","good morning","dawn"],char:'\u{1f307}',fitzpatrick_scale:!1,category:"travel_and_places"},city_sunset:{keywords:["photo","evening","sky","buildings"],char:'\u{1f306}',fitzpatrick_scale:!1,category:"travel_and_places"},cityscape:{keywords:["photo","night life","urban"],char:'\u{1f3d9}',fitzpatrick_scale:!1,category:"travel_and_places"},night_with_stars:{keywords:["evening","city","downtown"],char:'\u{1f303}',fitzpatrick_scale:!1,category:"travel_and_places"},bridge_at_night:{keywords:["photo","sanfrancisco"],char:'\u{1f309}',fitzpatrick_scale:!1,category:"travel_and_places"},milky_way:{keywords:["photo","space","stars"],char:'\u{1f30c}',fitzpatrick_scale:!1,category:"travel_and_places"},stars:{keywords:["night","photo"],char:'\u{1f320}',fitzpatrick_scale:!1,category:"travel_and_places"},sparkler:{keywords:["stars","night","shine"],char:'\u{1f387}',fitzpatrick_scale:!1,category:"travel_and_places"},fireworks:{keywords:["photo","festival","carnival","congratulations"],char:'\u{1f386}',fitzpatrick_scale:!1,category:"travel_and_places"},rainbow:{keywords:["nature","happy","unicorn_face","photo","sky","spring"],char:'\u{1f308}',fitzpatrick_scale:!1,category:"travel_and_places"},houses:{keywords:["buildings","photo"],char:'\u{1f3d8}',fitzpatrick_scale:!1,category:"travel_and_places"},european_castle:{keywords:["building","royalty","history"],char:'\u{1f3f0}',fitzpatrick_scale:!1,category:"travel_and_places"},japanese_castle:{keywords:["photo","building"],char:'\u{1f3ef}',fitzpatrick_scale:!1,category:"travel_and_places"},stadium:{keywords:["photo","place","sports","concert","venue"],char:'\u{1f3df}',fitzpatrick_scale:!1,category:"travel_and_places"},statue_of_liberty:{keywords:["american","newyork"],char:'\u{1f5fd}',fitzpatrick_scale:!1,category:"travel_and_places"},house:{keywords:["building","home"],char:'\u{1f3e0}',fitzpatrick_scale:!1,category:"travel_and_places"},house_with_garden:{keywords:["home","plant","nature"],char:'\u{1f3e1}',fitzpatrick_scale:!1,category:"travel_and_places"},derelict_house:{keywords:["abandon","evict","broken","building"],char:'\u{1f3da}',fitzpatrick_scale:!1,category:"travel_and_places"},office:{keywords:["building","bureau","work"],char:'\u{1f3e2}',fitzpatrick_scale:!1,category:"travel_and_places"},department_store:{keywords:["building","shopping","mall"],char:'\u{1f3ec}',fitzpatrick_scale:!1,category:"travel_and_places"},post_office:{keywords:["building","envelope","communication"],char:'\u{1f3e3}',fitzpatrick_scale:!1,category:"travel_and_places"},european_post_office:{keywords:["building","email"],char:'\u{1f3e4}',fitzpatrick_scale:!1,category:"travel_and_places"},hospital:{keywords:["building","health","surgery","doctor"],char:'\u{1f3e5}',fitzpatrick_scale:!1,category:"travel_and_places"},bank:{keywords:["building","money","sales","cash","business","enterprise"],char:'\u{1f3e6}',fitzpatrick_scale:!1,category:"travel_and_places"},hotel:{keywords:["building","accomodation","checkin"],char:'\u{1f3e8}',fitzpatrick_scale:!1,category:"travel_and_places"},convenience_store:{keywords:["building","shopping","groceries"],char:'\u{1f3ea}',fitzpatrick_scale:!1,category:"travel_and_places"},school:{keywords:["building","student","education","learn","teach"],char:'\u{1f3eb}',fitzpatrick_scale:!1,category:"travel_and_places"},love_hotel:{keywords:["like","affection","dating"],char:'\u{1f3e9}',fitzpatrick_scale:!1,category:"travel_and_places"},wedding:{keywords:["love","like","affection","couple","marriage","bride","groom"],char:'\u{1f492}',fitzpatrick_scale:!1,category:"travel_and_places"},classical_building:{keywords:["art","culture","history"],char:'\u{1f3db}',fitzpatrick_scale:!1,category:"travel_and_places"},church:{keywords:["building","religion","christ"],char:'\u26ea',fitzpatrick_scale:!1,category:"travel_and_places"},mosque:{keywords:["islam","worship","minaret"],char:'\u{1f54c}',fitzpatrick_scale:!1,category:"travel_and_places"},synagogue:{keywords:["judaism","worship","temple","jewish"],char:'\u{1f54d}',fitzpatrick_scale:!1,category:"travel_and_places"},kaaba:{keywords:["mecca","mosque","islam"],char:'\u{1f54b}',fitzpatrick_scale:!1,category:"travel_and_places"},shinto_shrine:{keywords:["temple","japan","kyoto"],char:'\u26e9',fitzpatrick_scale:!1,category:"travel_and_places"},watch:{keywords:["time","accessories"],char:'\u231a',fitzpatrick_scale:!1,category:"objects"},iphone:{keywords:["technology","apple","gadgets","dial"],char:'\u{1f4f1}',fitzpatrick_scale:!1,category:"objects"},calling:{keywords:["iphone","incoming"],char:'\u{1f4f2}',fitzpatrick_scale:!1,category:"objects"},computer:{keywords:["technology","laptop","screen","display","monitor"],char:'\u{1f4bb}',fitzpatrick_scale:!1,category:"objects"},keyboard:{keywords:["technology","computer","type","input","text"],char:'\u2328',fitzpatrick_scale:!1,category:"objects"},desktop_computer:{keywords:["technology","computing","screen"],char:'\u{1f5a5}',fitzpatrick_scale:!1,category:"objects"},printer:{keywords:["paper","ink"],char:'\u{1f5a8}',fitzpatrick_scale:!1,category:"objects"},computer_mouse:{keywords:["click"],char:'\u{1f5b1}',fitzpatrick_scale:!1,category:"objects"},trackball:{keywords:["technology","trackpad"],char:'\u{1f5b2}',fitzpatrick_scale:!1,category:"objects"},joystick:{keywords:["game","play"],char:'\u{1f579}',fitzpatrick_scale:!1,category:"objects"},clamp:{keywords:["tool"],char:'\u{1f5dc}',fitzpatrick_scale:!1,category:"objects"},minidisc:{keywords:["technology","record","data","disk","90s"],char:'\u{1f4bd}',fitzpatrick_scale:!1,category:"objects"},floppy_disk:{keywords:["oldschool","technology","save","90s","80s"],char:'\u{1f4be}',fitzpatrick_scale:!1,category:"objects"},cd:{keywords:["technology","dvd","disk","disc","90s"],char:'\u{1f4bf}',fitzpatrick_scale:!1,category:"objects"},dvd:{keywords:["cd","disk","disc"],char:'\u{1f4c0}',fitzpatrick_scale:!1,category:"objects"},vhs:{keywords:["record","video","oldschool","90s","80s"],char:'\u{1f4fc}',fitzpatrick_scale:!1,category:"objects"},camera:{keywords:["gadgets","photography"],char:'\u{1f4f7}',fitzpatrick_scale:!1,category:"objects"},camera_flash:{keywords:["photography","gadgets"],char:'\u{1f4f8}',fitzpatrick_scale:!1,category:"objects"},video_camera:{keywords:["film","record"],char:'\u{1f4f9}',fitzpatrick_scale:!1,category:"objects"},movie_camera:{keywords:["film","record"],char:'\u{1f3a5}',fitzpatrick_scale:!1,category:"objects"},film_projector:{keywords:["video","tape","record","movie"],char:'\u{1f4fd}',fitzpatrick_scale:!1,category:"objects"},film_strip:{keywords:["movie"],char:'\u{1f39e}',fitzpatrick_scale:!1,category:"objects"},telephone_receiver:{keywords:["technology","communication","dial"],char:'\u{1f4de}',fitzpatrick_scale:!1,category:"objects"},phone:{keywords:["technology","communication","dial","telephone"],char:'\u260e\ufe0f',fitzpatrick_scale:!1,category:"objects"},pager:{keywords:["bbcall","oldschool","90s"],char:'\u{1f4df}',fitzpatrick_scale:!1,category:"objects"},fax:{keywords:["communication","technology"],char:'\u{1f4e0}',fitzpatrick_scale:!1,category:"objects"},tv:{keywords:["technology","program","oldschool","show","television"],char:'\u{1f4fa}',fitzpatrick_scale:!1,category:"objects"},radio:{keywords:["communication","music","podcast","program"],char:'\u{1f4fb}',fitzpatrick_scale:!1,category:"objects"},studio_microphone:{keywords:["sing","recording","artist","talkshow"],char:'\u{1f399}',fitzpatrick_scale:!1,category:"objects"},level_slider:{keywords:["scale"],char:'\u{1f39a}',fitzpatrick_scale:!1,category:"objects"},control_knobs:{keywords:["dial"],char:'\u{1f39b}',fitzpatrick_scale:!1,category:"objects"},compass:{keywords:["magnetic","navigation","orienteering"],char:'\u{1f9ed}',fitzpatrick_scale:!1,category:"objects"},stopwatch:{keywords:["time","deadline"],char:'\u23f1',fitzpatrick_scale:!1,category:"objects"},timer_clock:{keywords:["alarm"],char:'\u23f2',fitzpatrick_scale:!1,category:"objects"},alarm_clock:{keywords:["time","wake"],char:'\u23f0',fitzpatrick_scale:!1,category:"objects"},mantelpiece_clock:{keywords:["time"],char:'\u{1f570}',fitzpatrick_scale:!1,category:"objects"},hourglass_flowing_sand:{keywords:["oldschool","time","countdown"],char:'\u23f3',fitzpatrick_scale:!1,category:"objects"},hourglass:{keywords:["time","clock","oldschool","limit","exam","quiz","test"],char:'\u231b',fitzpatrick_scale:!1,category:"objects"},satellite:{keywords:["communication","future","radio","space"],char:'\u{1f4e1}',fitzpatrick_scale:!1,category:"objects"},battery:{keywords:["power","energy","sustain"],char:'\u{1f50b}',fitzpatrick_scale:!1,category:"objects"},electric_plug:{keywords:["charger","power"],char:'\u{1f50c}',fitzpatrick_scale:!1,category:"objects"},bulb:{keywords:["light","electricity","idea"],char:'\u{1f4a1}',fitzpatrick_scale:!1,category:"objects"},flashlight:{keywords:["dark","camping","sight","night"],char:'\u{1f526}',fitzpatrick_scale:!1,category:"objects"},candle:{keywords:["fire","wax"],char:'\u{1f56f}',fitzpatrick_scale:!1,category:"objects"},fire_extinguisher:{keywords:["quench"],char:'\u{1f9ef}',fitzpatrick_scale:!1,category:"objects"},wastebasket:{keywords:["bin","trash","rubbish","garbage","toss"],char:'\u{1f5d1}',fitzpatrick_scale:!1,category:"objects"},oil_drum:{keywords:["barrell"],char:'\u{1f6e2}',fitzpatrick_scale:!1,category:"objects"},money_with_wings:{keywords:["dollar","bills","payment","sale"],char:'\u{1f4b8}',fitzpatrick_scale:!1,category:"objects"},dollar:{keywords:["money","sales","bill","currency"],char:'\u{1f4b5}',fitzpatrick_scale:!1,category:"objects"},yen:{keywords:["money","sales","japanese","dollar","currency"],char:'\u{1f4b4}',fitzpatrick_scale:!1,category:"objects"},euro:{keywords:["money","sales","dollar","currency"],char:'\u{1f4b6}',fitzpatrick_scale:!1,category:"objects"},pound:{keywords:["british","sterling","money","sales","bills","uk","england","currency"],char:'\u{1f4b7}',fitzpatrick_scale:!1,category:"objects"},moneybag:{keywords:["dollar","payment","coins","sale"],char:'\u{1f4b0}',fitzpatrick_scale:!1,category:"objects"},credit_card:{keywords:["money","sales","dollar","bill","payment","shopping"],char:'\u{1f4b3}',fitzpatrick_scale:!1,category:"objects"},gem:{keywords:["blue","ruby","diamond","jewelry"],char:'\u{1f48e}',fitzpatrick_scale:!1,category:"objects"},balance_scale:{keywords:["law","fairness","weight"],char:'\u2696',fitzpatrick_scale:!1,category:"objects"},toolbox:{keywords:["tools","diy","fix","maintainer","mechanic"],char:'\u{1f9f0}',fitzpatrick_scale:!1,category:"objects"},wrench:{keywords:["tools","diy","ikea","fix","maintainer"],char:'\u{1f527}',fitzpatrick_scale:!1,category:"objects"},hammer:{keywords:["tools","build","create"],char:'\u{1f528}',fitzpatrick_scale:!1,category:"objects"},hammer_and_pick:{keywords:["tools","build","create"],char:'\u2692',fitzpatrick_scale:!1,category:"objects"},hammer_and_wrench:{keywords:["tools","build","create"],char:'\u{1f6e0}',fitzpatrick_scale:!1,category:"objects"},pick:{keywords:["tools","dig"],char:'\u26cf',fitzpatrick_scale:!1,category:"objects"},nut_and_bolt:{keywords:["handy","tools","fix"],char:'\u{1f529}',fitzpatrick_scale:!1,category:"objects"},gear:{keywords:["cog"],char:'\u2699',fitzpatrick_scale:!1,category:"objects"},brick:{keywords:["bricks"],char:'\u{1f9f1}',fitzpatrick_scale:!1,category:"objects"},chains:{keywords:["lock","arrest"],char:'\u26d3',fitzpatrick_scale:!1,category:"objects"},magnet:{keywords:["attraction","magnetic"],char:'\u{1f9f2}',fitzpatrick_scale:!1,category:"objects"},gun:{keywords:["violence","weapon","pistol","revolver"],char:'\u{1f52b}',fitzpatrick_scale:!1,category:"objects"},bomb:{keywords:["boom","explode","explosion","terrorism"],char:'\u{1f4a3}',fitzpatrick_scale:!1,category:"objects"},firecracker:{keywords:["dynamite","boom","explode","explosion","explosive"],char:'\u{1f9e8}',fitzpatrick_scale:!1,category:"objects"},hocho:{keywords:["knife","blade","cutlery","kitchen","weapon"],char:'\u{1f52a}',fitzpatrick_scale:!1,category:"objects"},dagger:{keywords:["weapon"],char:'\u{1f5e1}',fitzpatrick_scale:!1,category:"objects"},crossed_swords:{keywords:["weapon"],char:'\u2694',fitzpatrick_scale:!1,category:"objects"},shield:{keywords:["protection","security"],char:'\u{1f6e1}',fitzpatrick_scale:!1,category:"objects"},smoking:{keywords:["kills","tobacco","cigarette","joint","smoke"],char:'\u{1f6ac}',fitzpatrick_scale:!1,category:"objects"},skull_and_crossbones:{keywords:["poison","danger","deadly","scary","death","pirate","evil"],char:'\u2620',fitzpatrick_scale:!1,category:"objects"},coffin:{keywords:["vampire","dead","die","death","rip","graveyard","cemetery","casket","funeral","box"],char:'\u26b0',fitzpatrick_scale:!1,category:"objects"},funeral_urn:{keywords:["dead","die","death","rip","ashes"],char:'\u26b1',fitzpatrick_scale:!1,category:"objects"},amphora:{keywords:["vase","jar"],char:'\u{1f3fa}',fitzpatrick_scale:!1,category:"objects"},crystal_ball:{keywords:["disco","party","magic","circus","fortune_teller"],char:'\u{1f52e}',fitzpatrick_scale:!1,category:"objects"},prayer_beads:{keywords:["dhikr","religious"],char:'\u{1f4ff}',fitzpatrick_scale:!1,category:"objects"},nazar_amulet:{keywords:["bead","charm"],char:'\u{1f9ff}',fitzpatrick_scale:!1,category:"objects"},barber:{keywords:["hair","salon","style"],char:'\u{1f488}',fitzpatrick_scale:!1,category:"objects"},alembic:{keywords:["distilling","science","experiment","chemistry"],char:'\u2697',fitzpatrick_scale:!1,category:"objects"},telescope:{keywords:["stars","space","zoom","science","astronomy"],char:'\u{1f52d}',fitzpatrick_scale:!1,category:"objects"},microscope:{keywords:["laboratory","experiment","zoomin","science","study"],char:'\u{1f52c}',fitzpatrick_scale:!1,category:"objects"},hole:{keywords:["embarrassing"],char:'\u{1f573}',fitzpatrick_scale:!1,category:"objects"},pill:{keywords:["health","medicine","doctor","pharmacy","drug"],char:'\u{1f48a}',fitzpatrick_scale:!1,category:"objects"},syringe:{keywords:["health","hospital","drugs","blood","medicine","needle","doctor","nurse"],char:'\u{1f489}',fitzpatrick_scale:!1,category:"objects"},dna:{keywords:["biologist","genetics","life"],char:'\u{1f9ec}',fitzpatrick_scale:!1,category:"objects"},microbe:{keywords:["amoeba","bacteria","germs"],char:'\u{1f9a0}',fitzpatrick_scale:!1,category:"objects"},petri_dish:{keywords:["bacteria","biology","culture","lab"],char:'\u{1f9eb}',fitzpatrick_scale:!1,category:"objects"},test_tube:{keywords:["chemistry","experiment","lab","science"],char:'\u{1f9ea}',fitzpatrick_scale:!1,category:"objects"},thermometer:{keywords:["weather","temperature","hot","cold"],char:'\u{1f321}',fitzpatrick_scale:!1,category:"objects"},broom:{keywords:["cleaning","sweeping","witch"],char:'\u{1f9f9}',fitzpatrick_scale:!1,category:"objects"},basket:{keywords:["laundry"],char:'\u{1f9fa}',fitzpatrick_scale:!1,category:"objects"},toilet_paper:{keywords:["roll"],char:'\u{1f9fb}',fitzpatrick_scale:!1,category:"objects"},label:{keywords:["sale","tag"],char:'\u{1f3f7}',fitzpatrick_scale:!1,category:"objects"},bookmark:{keywords:["favorite","label","save"],char:'\u{1f516}',fitzpatrick_scale:!1,category:"objects"},toilet:{keywords:["restroom","wc","washroom","bathroom","potty"],char:'\u{1f6bd}',fitzpatrick_scale:!1,category:"objects"},shower:{keywords:["clean","water","bathroom"],char:'\u{1f6bf}',fitzpatrick_scale:!1,category:"objects"},bathtub:{keywords:["clean","shower","bathroom"],char:'\u{1f6c1}',fitzpatrick_scale:!1,category:"objects"},soap:{keywords:["bar","bathing","cleaning","lather"],char:'\u{1f9fc}',fitzpatrick_scale:!1,category:"objects"},sponge:{keywords:["absorbing","cleaning","porous"],char:'\u{1f9fd}',fitzpatrick_scale:!1,category:"objects"},lotion_bottle:{keywords:["moisturizer","sunscreen"],char:'\u{1f9f4}',fitzpatrick_scale:!1,category:"objects"},key:{keywords:["lock","door","password"],char:'\u{1f511}',fitzpatrick_scale:!1,category:"objects"},old_key:{keywords:["lock","door","password"],char:'\u{1f5dd}',fitzpatrick_scale:!1,category:"objects"},couch_and_lamp:{keywords:["read","chill"],char:'\u{1f6cb}',fitzpatrick_scale:!1,category:"objects"},sleeping_bed:{keywords:["bed","rest"],char:'\u{1f6cc}',fitzpatrick_scale:!0,category:"objects"},bed:{keywords:["sleep","rest"],char:'\u{1f6cf}',fitzpatrick_scale:!1,category:"objects"},door:{keywords:["house","entry","exit"],char:'\u{1f6aa}',fitzpatrick_scale:!1,category:"objects"},bellhop_bell:{keywords:["service"],char:'\u{1f6ce}',fitzpatrick_scale:!1,category:"objects"},teddy_bear:{keywords:["plush","stuffed"],char:'\u{1f9f8}',fitzpatrick_scale:!1,category:"objects"},framed_picture:{keywords:["photography"],char:'\u{1f5bc}',fitzpatrick_scale:!1,category:"objects"},world_map:{keywords:["location","direction"],char:'\u{1f5fa}',fitzpatrick_scale:!1,category:"objects"},parasol_on_ground:{keywords:["weather","summer"],char:'\u26f1',fitzpatrick_scale:!1,category:"objects"},moyai:{keywords:["rock","easter island","moai"],char:'\u{1f5ff}',fitzpatrick_scale:!1,category:"objects"},shopping:{keywords:["mall","buy","purchase"],char:'\u{1f6cd}',fitzpatrick_scale:!1,category:"objects"},shopping_cart:{keywords:["trolley"],char:'\u{1f6d2}',fitzpatrick_scale:!1,category:"objects"},balloon:{keywords:["party","celebration","birthday","circus"],char:'\u{1f388}',fitzpatrick_scale:!1,category:"objects"},flags:{keywords:["fish","japanese","koinobori","carp","banner"],char:'\u{1f38f}',fitzpatrick_scale:!1,category:"objects"},ribbon:{keywords:["decoration","pink","girl","bowtie"],char:'\u{1f380}',fitzpatrick_scale:!1,category:"objects"},gift:{keywords:["present","birthday","christmas","xmas"],char:'\u{1f381}',fitzpatrick_scale:!1,category:"objects"},confetti_ball:{keywords:["festival","party","birthday","circus"],char:'\u{1f38a}',fitzpatrick_scale:!1,category:"objects"},tada:{keywords:["party","congratulations","birthday","magic","circus","celebration"],char:'\u{1f389}',fitzpatrick_scale:!1,category:"objects"},dolls:{keywords:["japanese","toy","kimono"],char:'\u{1f38e}',fitzpatrick_scale:!1,category:"objects"},wind_chime:{keywords:["nature","ding","spring","bell"],char:'\u{1f390}',fitzpatrick_scale:!1,category:"objects"},crossed_flags:{keywords:["japanese","nation","country","border"],char:'\u{1f38c}',fitzpatrick_scale:!1,category:"objects"},izakaya_lantern:{keywords:["light","paper","halloween","spooky"],char:'\u{1f3ee}',fitzpatrick_scale:!1,category:"objects"},red_envelope:{keywords:["gift"],char:'\u{1f9e7}',fitzpatrick_scale:!1,category:"objects"},email:{keywords:["letter","postal","inbox","communication"],char:'\u2709\ufe0f',fitzpatrick_scale:!1,category:"objects"},envelope_with_arrow:{keywords:["email","communication"],char:'\u{1f4e9}',fitzpatrick_scale:!1,category:"objects"},incoming_envelope:{keywords:["email","inbox"],char:'\u{1f4e8}',fitzpatrick_scale:!1,category:"objects"},"e-mail":{keywords:["communication","inbox"],char:'\u{1f4e7}',fitzpatrick_scale:!1,category:"objects"},love_letter:{keywords:["email","like","affection","envelope","valentines"],char:'\u{1f48c}',fitzpatrick_scale:!1,category:"objects"},postbox:{keywords:["email","letter","envelope"],char:'\u{1f4ee}',fitzpatrick_scale:!1,category:"objects"},mailbox_closed:{keywords:["email","communication","inbox"],char:'\u{1f4ea}',fitzpatrick_scale:!1,category:"objects"},mailbox:{keywords:["email","inbox","communication"],char:'\u{1f4eb}',fitzpatrick_scale:!1,category:"objects"},mailbox_with_mail:{keywords:["email","inbox","communication"],char:'\u{1f4ec}',fitzpatrick_scale:!1,category:"objects"},mailbox_with_no_mail:{keywords:["email","inbox"],char:'\u{1f4ed}',fitzpatrick_scale:!1,category:"objects"},package:{keywords:["mail","gift","cardboard","box","moving"],char:'\u{1f4e6}',fitzpatrick_scale:!1,category:"objects"},postal_horn:{keywords:["instrument","music"],char:'\u{1f4ef}',fitzpatrick_scale:!1,category:"objects"},inbox_tray:{keywords:["email","documents"],char:'\u{1f4e5}',fitzpatrick_scale:!1,category:"objects"},outbox_tray:{keywords:["inbox","email"],char:'\u{1f4e4}',fitzpatrick_scale:!1,category:"objects"},scroll:{keywords:["documents","ancient","history","paper"],char:'\u{1f4dc}',fitzpatrick_scale:!1,category:"objects"},page_with_curl:{keywords:["documents","office","paper"],char:'\u{1f4c3}',fitzpatrick_scale:!1,category:"objects"},bookmark_tabs:{keywords:["favorite","save","order","tidy"],char:'\u{1f4d1}',fitzpatrick_scale:!1,category:"objects"},receipt:{keywords:["accounting","expenses"],char:'\u{1f9fe}',fitzpatrick_scale:!1,category:"objects"},bar_chart:{keywords:["graph","presentation","stats"],char:'\u{1f4ca}',fitzpatrick_scale:!1,category:"objects"},chart_with_upwards_trend:{keywords:["graph","presentation","stats","recovery","business","economics","money","sales","good","success"],char:'\u{1f4c8}',fitzpatrick_scale:!1,category:"objects"},chart_with_downwards_trend:{keywords:["graph","presentation","stats","recession","business","economics","money","sales","bad","failure"],char:'\u{1f4c9}',fitzpatrick_scale:!1,category:"objects"},page_facing_up:{keywords:["documents","office","paper","information"],char:'\u{1f4c4}',fitzpatrick_scale:!1,category:"objects"},date:{keywords:["calendar","schedule"],char:'\u{1f4c5}',fitzpatrick_scale:!1,category:"objects"},calendar:{keywords:["schedule","date","planning"],char:'\u{1f4c6}',fitzpatrick_scale:!1,category:"objects"},spiral_calendar:{keywords:["date","schedule","planning"],char:'\u{1f5d3}',fitzpatrick_scale:!1,category:"objects"},card_index:{keywords:["business","stationery"],char:'\u{1f4c7}',fitzpatrick_scale:!1,category:"objects"},card_file_box:{keywords:["business","stationery"],char:'\u{1f5c3}',fitzpatrick_scale:!1,category:"objects"},ballot_box:{keywords:["election","vote"],char:'\u{1f5f3}',fitzpatrick_scale:!1,category:"objects"},file_cabinet:{keywords:["filing","organizing"],char:'\u{1f5c4}',fitzpatrick_scale:!1,category:"objects"},clipboard:{keywords:["stationery","documents"],char:'\u{1f4cb}',fitzpatrick_scale:!1,category:"objects"},spiral_notepad:{keywords:["memo","stationery"],char:'\u{1f5d2}',fitzpatrick_scale:!1,category:"objects"},file_folder:{keywords:["documents","business","office"],char:'\u{1f4c1}',fitzpatrick_scale:!1,category:"objects"},open_file_folder:{keywords:["documents","load"],char:'\u{1f4c2}',fitzpatrick_scale:!1,category:"objects"},card_index_dividers:{keywords:["organizing","business","stationery"],char:'\u{1f5c2}',fitzpatrick_scale:!1,category:"objects"},newspaper_roll:{keywords:["press","headline"],char:'\u{1f5de}',fitzpatrick_scale:!1,category:"objects"},newspaper:{keywords:["press","headline"],char:'\u{1f4f0}',fitzpatrick_scale:!1,category:"objects"},notebook:{keywords:["stationery","record","notes","paper","study"],char:'\u{1f4d3}',fitzpatrick_scale:!1,category:"objects"},closed_book:{keywords:["read","library","knowledge","textbook","learn"],char:'\u{1f4d5}',fitzpatrick_scale:!1,category:"objects"},green_book:{keywords:["read","library","knowledge","study"],char:'\u{1f4d7}',fitzpatrick_scale:!1,category:"objects"},blue_book:{keywords:["read","library","knowledge","learn","study"],char:'\u{1f4d8}',fitzpatrick_scale:!1,category:"objects"},orange_book:{keywords:["read","library","knowledge","textbook","study"],char:'\u{1f4d9}',fitzpatrick_scale:!1,category:"objects"},notebook_with_decorative_cover:{keywords:["classroom","notes","record","paper","study"],char:'\u{1f4d4}',fitzpatrick_scale:!1,category:"objects"},ledger:{keywords:["notes","paper"],char:'\u{1f4d2}',fitzpatrick_scale:!1,category:"objects"},books:{keywords:["literature","library","study"],char:'\u{1f4da}',fitzpatrick_scale:!1,category:"objects"},open_book:{keywords:["book","read","library","knowledge","literature","learn","study"],char:'\u{1f4d6}',fitzpatrick_scale:!1,category:"objects"},safety_pin:{keywords:["diaper"],char:'\u{1f9f7}',fitzpatrick_scale:!1,category:"objects"},link:{keywords:["rings","url"],char:'\u{1f517}',fitzpatrick_scale:!1,category:"objects"},paperclip:{keywords:["documents","stationery"],char:'\u{1f4ce}',fitzpatrick_scale:!1,category:"objects"},paperclips:{keywords:["documents","stationery"],char:'\u{1f587}',fitzpatrick_scale:!1,category:"objects"},scissors:{keywords:["stationery","cut"],char:'\u2702\ufe0f',fitzpatrick_scale:!1,category:"objects"},triangular_ruler:{keywords:["stationery","math","architect","sketch"],char:'\u{1f4d0}',fitzpatrick_scale:!1,category:"objects"},straight_ruler:{keywords:["stationery","calculate","length","math","school","drawing","architect","sketch"],char:'\u{1f4cf}',fitzpatrick_scale:!1,category:"objects"},abacus:{keywords:["calculation"],char:'\u{1f9ee}',fitzpatrick_scale:!1,category:"objects"},pushpin:{keywords:["stationery","mark","here"],char:'\u{1f4cc}',fitzpatrick_scale:!1,category:"objects"},round_pushpin:{keywords:["stationery","location","map","here"],char:'\u{1f4cd}',fitzpatrick_scale:!1,category:"objects"},triangular_flag_on_post:{keywords:["mark","milestone","place"],char:'\u{1f6a9}',fitzpatrick_scale:!1,category:"objects"},white_flag:{keywords:["losing","loser","lost","surrender","give up","fail"],char:'\u{1f3f3}',fitzpatrick_scale:!1,category:"objects"},black_flag:{keywords:["pirate"],char:'\u{1f3f4}',fitzpatrick_scale:!1,category:"objects"},rainbow_flag:{keywords:["flag","rainbow","pride","gay","lgbt","glbt","queer","homosexual","lesbian","bisexual","transgender"],char:'\u{1f3f3}\ufe0f\u200d\u{1f308}',fitzpatrick_scale:!1,category:"objects"},closed_lock_with_key:{keywords:["security","privacy"],char:'\u{1f510}',fitzpatrick_scale:!1,category:"objects"},lock:{keywords:["security","password","padlock"],char:'\u{1f512}',fitzpatrick_scale:!1,category:"objects"},unlock:{keywords:["privacy","security"],char:'\u{1f513}',fitzpatrick_scale:!1,category:"objects"},lock_with_ink_pen:{keywords:["security","secret"],char:'\u{1f50f}',fitzpatrick_scale:!1,category:"objects"},pen:{keywords:["stationery","writing","write"],char:'\u{1f58a}',fitzpatrick_scale:!1,category:"objects"},fountain_pen:{keywords:["stationery","writing","write"],char:'\u{1f58b}',fitzpatrick_scale:!1,category:"objects"},black_nib:{keywords:["pen","stationery","writing","write"],char:'\u2712\ufe0f',fitzpatrick_scale:!1,category:"objects"},memo:{keywords:["write","documents","stationery","pencil","paper","writing","legal","exam","quiz","test","study","compose"],char:'\u{1f4dd}',fitzpatrick_scale:!1,category:"objects"},pencil2:{keywords:["stationery","write","paper","writing","school","study"],char:'\u270f\ufe0f',fitzpatrick_scale:!1,category:"objects"},crayon:{keywords:["drawing","creativity"],char:'\u{1f58d}',fitzpatrick_scale:!1,category:"objects"},paintbrush:{keywords:["drawing","creativity","art"],char:'\u{1f58c}',fitzpatrick_scale:!1,category:"objects"},mag:{keywords:["search","zoom","find","detective"],char:'\u{1f50d}',fitzpatrick_scale:!1,category:"objects"},mag_right:{keywords:["search","zoom","find","detective"],char:'\u{1f50e}',fitzpatrick_scale:!1,category:"objects"},heart:{keywords:["love","like","valentines"],char:'\u2764\ufe0f',fitzpatrick_scale:!1,category:"symbols"},orange_heart:{keywords:["love","like","affection","valentines"],char:'\u{1f9e1}',fitzpatrick_scale:!1,category:"symbols"},yellow_heart:{keywords:["love","like","affection","valentines"],char:'\u{1f49b}',fitzpatrick_scale:!1,category:"symbols"},green_heart:{keywords:["love","like","affection","valentines"],char:'\u{1f49a}',fitzpatrick_scale:!1,category:"symbols"},blue_heart:{keywords:["love","like","affection","valentines"],char:'\u{1f499}',fitzpatrick_scale:!1,category:"symbols"},purple_heart:{keywords:["love","like","affection","valentines"],char:'\u{1f49c}',fitzpatrick_scale:!1,category:"symbols"},black_heart:{keywords:["evil"],char:'\u{1f5a4}',fitzpatrick_scale:!1,category:"symbols"},broken_heart:{keywords:["sad","sorry","break","heart","heartbreak"],char:'\u{1f494}',fitzpatrick_scale:!1,category:"symbols"},heavy_heart_exclamation:{keywords:["decoration","love"],char:'\u2763',fitzpatrick_scale:!1,category:"symbols"},two_hearts:{keywords:["love","like","affection","valentines","heart"],char:'\u{1f495}',fitzpatrick_scale:!1,category:"symbols"},revolving_hearts:{keywords:["love","like","affection","valentines"],char:'\u{1f49e}',fitzpatrick_scale:!1,category:"symbols"},heartbeat:{keywords:["love","like","affection","valentines","pink","heart"],char:'\u{1f493}',fitzpatrick_scale:!1,category:"symbols"},heartpulse:{keywords:["like","love","affection","valentines","pink"],char:'\u{1f497}',fitzpatrick_scale:!1,category:"symbols"},sparkling_heart:{keywords:["love","like","affection","valentines"],char:'\u{1f496}',fitzpatrick_scale:!1,category:"symbols"},cupid:{keywords:["love","like","heart","affection","valentines"],char:'\u{1f498}',fitzpatrick_scale:!1,category:"symbols"},gift_heart:{keywords:["love","valentines"],char:'\u{1f49d}',fitzpatrick_scale:!1,category:"symbols"},heart_decoration:{keywords:["purple-square","love","like"],char:'\u{1f49f}',fitzpatrick_scale:!1,category:"symbols"},peace_symbol:{keywords:["hippie"],char:'\u262e',fitzpatrick_scale:!1,category:"symbols"},latin_cross:{keywords:["christianity"],char:'\u271d',fitzpatrick_scale:!1,category:"symbols"},star_and_crescent:{keywords:["islam"],char:'\u262a',fitzpatrick_scale:!1,category:"symbols"},om:{keywords:["hinduism","buddhism","sikhism","jainism"],char:'\u{1f549}',fitzpatrick_scale:!1,category:"symbols"},wheel_of_dharma:{keywords:["hinduism","buddhism","sikhism","jainism"],char:'\u2638',fitzpatrick_scale:!1,category:"symbols"},star_of_david:{keywords:["judaism"],char:'\u2721',fitzpatrick_scale:!1,category:"symbols"},six_pointed_star:{keywords:["purple-square","religion","jewish","hexagram"],char:'\u{1f52f}',fitzpatrick_scale:!1,category:"symbols"},menorah:{keywords:["hanukkah","candles","jewish"],char:'\u{1f54e}',fitzpatrick_scale:!1,category:"symbols"},yin_yang:{keywords:["balance"],char:'\u262f',fitzpatrick_scale:!1,category:"symbols"},orthodox_cross:{keywords:["suppedaneum","religion"],char:'\u2626',fitzpatrick_scale:!1,category:"symbols"},place_of_worship:{keywords:["religion","church","temple","prayer"],char:'\u{1f6d0}',fitzpatrick_scale:!1,category:"symbols"},ophiuchus:{keywords:["sign","purple-square","constellation","astrology"],char:'\u26ce',fitzpatrick_scale:!1,category:"symbols"},aries:{keywords:["sign","purple-square","zodiac","astrology"],char:'\u2648',fitzpatrick_scale:!1,category:"symbols"},taurus:{keywords:["purple-square","sign","zodiac","astrology"],char:'\u2649',fitzpatrick_scale:!1,category:"symbols"},gemini:{keywords:["sign","zodiac","purple-square","astrology"],char:'\u264a',fitzpatrick_scale:!1,category:"symbols"},cancer:{keywords:["sign","zodiac","purple-square","astrology"],char:'\u264b',fitzpatrick_scale:!1,category:"symbols"},leo:{keywords:["sign","purple-square","zodiac","astrology"],char:'\u264c',fitzpatrick_scale:!1,category:"symbols"},virgo:{keywords:["sign","zodiac","purple-square","astrology"],char:'\u264d',fitzpatrick_scale:!1,category:"symbols"},libra:{keywords:["sign","purple-square","zodiac","astrology"],char:'\u264e',fitzpatrick_scale:!1,category:"symbols"},scorpius:{keywords:["sign","zodiac","purple-square","astrology","scorpio"],char:'\u264f',fitzpatrick_scale:!1,category:"symbols"},sagittarius:{keywords:["sign","zodiac","purple-square","astrology"],char:'\u2650',fitzpatrick_scale:!1,category:"symbols"},capricorn:{keywords:["sign","zodiac","purple-square","astrology"],char:'\u2651',fitzpatrick_scale:!1,category:"symbols"},aquarius:{keywords:["sign","purple-square","zodiac","astrology"],char:'\u2652',fitzpatrick_scale:!1,category:"symbols"},pisces:{keywords:["purple-square","sign","zodiac","astrology"],char:'\u2653',fitzpatrick_scale:!1,category:"symbols"},id:{keywords:["purple-square","words"],char:'\u{1f194}',fitzpatrick_scale:!1,category:"symbols"},atom_symbol:{keywords:["science","physics","chemistry"],char:'\u269b',fitzpatrick_scale:!1,category:"symbols"},u7a7a:{keywords:["kanji","japanese","chinese","empty","sky","blue-square"],char:'\u{1f233}',fitzpatrick_scale:!1,category:"symbols"},u5272:{keywords:["cut","divide","chinese","kanji","pink-square"],char:'\u{1f239}',fitzpatrick_scale:!1,category:"symbols"},radioactive:{keywords:["nuclear","danger"],char:'\u2622',fitzpatrick_scale:!1,category:"symbols"},biohazard:{keywords:["danger"],char:'\u2623',fitzpatrick_scale:!1,category:"symbols"},mobile_phone_off:{keywords:["mute","orange-square","silence","quiet"],char:'\u{1f4f4}',fitzpatrick_scale:!1,category:"symbols"},vibration_mode:{keywords:["orange-square","phone"],char:'\u{1f4f3}',fitzpatrick_scale:!1,category:"symbols"},u6709:{keywords:["orange-square","chinese","have","kanji"],char:'\u{1f236}',fitzpatrick_scale:!1,category:"symbols"},u7121:{keywords:["nothing","chinese","kanji","japanese","orange-square"],char:'\u{1f21a}',fitzpatrick_scale:!1,category:"symbols"},u7533:{keywords:["chinese","japanese","kanji","orange-square"],char:'\u{1f238}',fitzpatrick_scale:!1,category:"symbols"},u55b6:{keywords:["japanese","opening hours","orange-square"],char:'\u{1f23a}',fitzpatrick_scale:!1,category:"symbols"},u6708:{keywords:["chinese","month","moon","japanese","orange-square","kanji"],char:'\u{1f237}\ufe0f',fitzpatrick_scale:!1,category:"symbols"},eight_pointed_black_star:{keywords:["orange-square","shape","polygon"],char:'\u2734\ufe0f',fitzpatrick_scale:!1,category:"symbols"},vs:{keywords:["words","orange-square"],char:'\u{1f19a}',fitzpatrick_scale:!1,category:"symbols"},accept:{keywords:["ok","good","chinese","kanji","agree","yes","orange-circle"],char:'\u{1f251}',fitzpatrick_scale:!1,category:"symbols"},white_flower:{keywords:["japanese","spring"],char:'\u{1f4ae}',fitzpatrick_scale:!1,category:"symbols"},ideograph_advantage:{keywords:["chinese","kanji","obtain","get","circle"],char:'\u{1f250}',fitzpatrick_scale:!1,category:"symbols"},secret:{keywords:["privacy","chinese","sshh","kanji","red-circle"],char:'\u3299\ufe0f',fitzpatrick_scale:!1,category:"symbols"},congratulations:{keywords:["chinese","kanji","japanese","red-circle"],char:'\u3297\ufe0f',fitzpatrick_scale:!1,category:"symbols"},u5408:{keywords:["japanese","chinese","join","kanji","red-square"],char:'\u{1f234}',fitzpatrick_scale:!1,category:"symbols"},u6e80:{keywords:["full","chinese","japanese","red-square","kanji"],char:'\u{1f235}',fitzpatrick_scale:!1,category:"symbols"},u7981:{keywords:["kanji","japanese","chinese","forbidden","limit","restricted","red-square"],char:'\u{1f232}',fitzpatrick_scale:!1,category:"symbols"},a:{keywords:["red-square","alphabet","letter"],char:'\u{1f170}\ufe0f',fitzpatrick_scale:!1,category:"symbols"},b:{keywords:["red-square","alphabet","letter"],char:'\u{1f171}\ufe0f',fitzpatrick_scale:!1,category:"symbols"},ab:{keywords:["red-square","alphabet"],char:'\u{1f18e}',fitzpatrick_scale:!1,category:"symbols"},cl:{keywords:["alphabet","words","red-square"],char:'\u{1f191}',fitzpatrick_scale:!1,category:"symbols"},o2:{keywords:["alphabet","red-square","letter"],char:'\u{1f17e}\ufe0f',fitzpatrick_scale:!1,category:"symbols"},sos:{keywords:["help","red-square","words","emergency","911"],char:'\u{1f198}',fitzpatrick_scale:!1,category:"symbols"},no_entry:{keywords:["limit","security","privacy","bad","denied","stop","circle"],char:'\u26d4',fitzpatrick_scale:!1,category:"symbols"},name_badge:{keywords:["fire","forbid"],char:'\u{1f4db}',fitzpatrick_scale:!1,category:"symbols"},no_entry_sign:{keywords:["forbid","stop","limit","denied","disallow","circle"],char:'\u{1f6ab}',fitzpatrick_scale:!1,category:"symbols"},x:{keywords:["no","delete","remove","cancel","red"],char:'\u274c',fitzpatrick_scale:!1,category:"symbols"},o:{keywords:["circle","round"],char:'\u2b55',fitzpatrick_scale:!1,category:"symbols"},stop_sign:{keywords:["stop"],char:'\u{1f6d1}',fitzpatrick_scale:!1,category:"symbols"},anger:{keywords:["angry","mad"],char:'\u{1f4a2}',fitzpatrick_scale:!1,category:"symbols"},hotsprings:{keywords:["bath","warm","relax"],char:'\u2668\ufe0f',fitzpatrick_scale:!1,category:"symbols"},no_pedestrians:{keywords:["rules","crossing","walking","circle"],char:'\u{1f6b7}',fitzpatrick_scale:!1,category:"symbols"},do_not_litter:{keywords:["trash","bin","garbage","circle"],char:'\u{1f6af}',fitzpatrick_scale:!1,category:"symbols"},no_bicycles:{keywords:["cyclist","prohibited","circle"],char:'\u{1f6b3}',fitzpatrick_scale:!1,category:"symbols"},"non-potable_water":{keywords:["drink","faucet","tap","circle"],char:'\u{1f6b1}',fitzpatrick_scale:!1,category:"symbols"},underage:{keywords:["18","drink","pub","night","minor","circle"],char:'\u{1f51e}',fitzpatrick_scale:!1,category:"symbols"},no_mobile_phones:{keywords:["iphone","mute","circle"],char:'\u{1f4f5}',fitzpatrick_scale:!1,category:"symbols"},exclamation:{keywords:["heavy_exclamation_mark","danger","surprise","punctuation","wow","warning"],char:'\u2757',fitzpatrick_scale:!1,category:"symbols"},grey_exclamation:{keywords:["surprise","punctuation","gray","wow","warning"],char:'\u2755',fitzpatrick_scale:!1,category:"symbols"},question:{keywords:["doubt","confused"],char:'\u2753',fitzpatrick_scale:!1,category:"symbols"},grey_question:{keywords:["doubts","gray","huh","confused"],char:'\u2754',fitzpatrick_scale:!1,category:"symbols"},bangbang:{keywords:["exclamation","surprise"],char:'\u203c\ufe0f',fitzpatrick_scale:!1,category:"symbols"},interrobang:{keywords:["wat","punctuation","surprise"],char:'\u2049\ufe0f',fitzpatrick_scale:!1,category:"symbols"},low_brightness:{keywords:["sun","afternoon","warm","summer"],char:'\u{1f505}',fitzpatrick_scale:!1,category:"symbols"},high_brightness:{keywords:["sun","light"],char:'\u{1f506}',fitzpatrick_scale:!1,category:"symbols"},trident:{keywords:["weapon","spear"],char:'\u{1f531}',fitzpatrick_scale:!1,category:"symbols"},fleur_de_lis:{keywords:["decorative","scout"],char:'\u269c',fitzpatrick_scale:!1,category:"symbols"},part_alternation_mark:{keywords:["graph","presentation","stats","business","economics","bad"],char:'\u303d\ufe0f',fitzpatrick_scale:!1,category:"symbols"},warning:{keywords:["exclamation","wip","alert","error","problem","issue"],char:'\u26a0\ufe0f',fitzpatrick_scale:!1,category:"symbols"},children_crossing:{keywords:["school","warning","danger","sign","driving","yellow-diamond"],char:'\u{1f6b8}',fitzpatrick_scale:!1,category:"symbols"},beginner:{keywords:["badge","shield"],char:'\u{1f530}',fitzpatrick_scale:!1,category:"symbols"},recycle:{keywords:["arrow","environment","garbage","trash"],char:'\u267b\ufe0f',fitzpatrick_scale:!1,category:"symbols"},u6307:{keywords:["chinese","point","green-square","kanji"],char:'\u{1f22f}',fitzpatrick_scale:!1,category:"symbols"},chart:{keywords:["green-square","graph","presentation","stats"],char:'\u{1f4b9}',fitzpatrick_scale:!1,category:"symbols"},sparkle:{keywords:["stars","green-square","awesome","good","fireworks"],char:'\u2747\ufe0f',fitzpatrick_scale:!1,category:"symbols"},eight_spoked_asterisk:{keywords:["star","sparkle","green-square"],char:'\u2733\ufe0f',fitzpatrick_scale:!1,category:"symbols"},negative_squared_cross_mark:{keywords:["x","green-square","no","deny"],char:'\u274e',fitzpatrick_scale:!1,category:"symbols"},white_check_mark:{keywords:["green-square","ok","agree","vote","election","answer","tick"],char:'\u2705',fitzpatrick_scale:!1,category:"symbols"},diamond_shape_with_a_dot_inside:{keywords:["jewel","blue","gem","crystal","fancy"],char:'\u{1f4a0}',fitzpatrick_scale:!1,category:"symbols"},cyclone:{keywords:["weather","swirl","blue","cloud","vortex","spiral","whirlpool","spin","tornado","hurricane","typhoon"],char:'\u{1f300}',fitzpatrick_scale:!1,category:"symbols"},loop:{keywords:["tape","cassette"],char:'\u27bf',fitzpatrick_scale:!1,category:"symbols"},globe_with_meridians:{keywords:["earth","international","world","internet","interweb","i18n"],char:'\u{1f310}',fitzpatrick_scale:!1,category:"symbols"},m:{keywords:["alphabet","blue-circle","letter"],char:'\u24c2\ufe0f',fitzpatrick_scale:!1,category:"symbols"},atm:{keywords:["money","sales","cash","blue-square","payment","bank"],char:'\u{1f3e7}',fitzpatrick_scale:!1,category:"symbols"},sa:{keywords:["japanese","blue-square","katakana"],char:'\u{1f202}\ufe0f',fitzpatrick_scale:!1,category:"symbols"},passport_control:{keywords:["custom","blue-square"],char:'\u{1f6c2}',fitzpatrick_scale:!1,category:"symbols"},customs:{keywords:["passport","border","blue-square"],char:'\u{1f6c3}',fitzpatrick_scale:!1,category:"symbols"},baggage_claim:{keywords:["blue-square","airport","transport"],char:'\u{1f6c4}',fitzpatrick_scale:!1,category:"symbols"},left_luggage:{keywords:["blue-square","travel"],char:'\u{1f6c5}',fitzpatrick_scale:!1,category:"symbols"},wheelchair:{keywords:["blue-square","disabled","a11y","accessibility"],char:'\u267f',fitzpatrick_scale:!1,category:"symbols"},no_smoking:{keywords:["cigarette","blue-square","smell","smoke"],char:'\u{1f6ad}',fitzpatrick_scale:!1,category:"symbols"},wc:{keywords:["toilet","restroom","blue-square"],char:'\u{1f6be}',fitzpatrick_scale:!1,category:"symbols"},parking:{keywords:["cars","blue-square","alphabet","letter"],char:'\u{1f17f}\ufe0f',fitzpatrick_scale:!1,category:"symbols"},potable_water:{keywords:["blue-square","liquid","restroom","cleaning","faucet"],char:'\u{1f6b0}',fitzpatrick_scale:!1,category:"symbols"},mens:{keywords:["toilet","restroom","wc","blue-square","gender","male"],char:'\u{1f6b9}',fitzpatrick_scale:!1,category:"symbols"},womens:{keywords:["purple-square","woman","female","toilet","loo","restroom","gender"],char:'\u{1f6ba}',fitzpatrick_scale:!1,category:"symbols"},baby_symbol:{keywords:["orange-square","child"],char:'\u{1f6bc}',fitzpatrick_scale:!1,category:"symbols"},restroom:{keywords:["blue-square","toilet","refresh","wc","gender"],char:'\u{1f6bb}',fitzpatrick_scale:!1,category:"symbols"},put_litter_in_its_place:{keywords:["blue-square","sign","human","info"],char:'\u{1f6ae}',fitzpatrick_scale:!1,category:"symbols"},cinema:{keywords:["blue-square","record","film","movie","curtain","stage","theater"],char:'\u{1f3a6}',fitzpatrick_scale:!1,category:"symbols"},signal_strength:{keywords:["blue-square","reception","phone","internet","connection","wifi","bluetooth","bars"],char:'\u{1f4f6}',fitzpatrick_scale:!1,category:"symbols"},koko:{keywords:["blue-square","here","katakana","japanese","destination"],char:'\u{1f201}',fitzpatrick_scale:!1,category:"symbols"},ng:{keywords:["blue-square","words","shape","icon"],char:'\u{1f196}',fitzpatrick_scale:!1,category:"symbols"},ok:{keywords:["good","agree","yes","blue-square"],char:'\u{1f197}',fitzpatrick_scale:!1,category:"symbols"},up:{keywords:["blue-square","above","high"],char:'\u{1f199}',fitzpatrick_scale:!1,category:"symbols"},cool:{keywords:["words","blue-square"],char:'\u{1f192}',fitzpatrick_scale:!1,category:"symbols"},new:{keywords:["blue-square","words","start"],char:'\u{1f195}',fitzpatrick_scale:!1,category:"symbols"},free:{keywords:["blue-square","words"],char:'\u{1f193}',fitzpatrick_scale:!1,category:"symbols"},zero:{keywords:["0","numbers","blue-square","null"],char:'0\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},one:{keywords:["blue-square","numbers","1"],char:'1\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},two:{keywords:["numbers","2","prime","blue-square"],char:'2\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},three:{keywords:["3","numbers","prime","blue-square"],char:'3\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},four:{keywords:["4","numbers","blue-square"],char:'4\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},five:{keywords:["5","numbers","blue-square","prime"],char:'5\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},six:{keywords:["6","numbers","blue-square"],char:'6\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},seven:{keywords:["7","numbers","blue-square","prime"],char:'7\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},eight:{keywords:["8","blue-square","numbers"],char:'8\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},nine:{keywords:["blue-square","numbers","9"],char:'9\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},keycap_ten:{keywords:["numbers","10","blue-square"],char:'\u{1f51f}',fitzpatrick_scale:!1,category:"symbols"},asterisk:{keywords:["star","keycap"],char:'*\u20e3',fitzpatrick_scale:!1,category:"symbols"},eject_button:{keywords:["blue-square"],char:'\u23cf\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_forward:{keywords:["blue-square","right","direction","play"],char:'\u25b6\ufe0f',fitzpatrick_scale:!1,category:"symbols"},pause_button:{keywords:["pause","blue-square"],char:'\u23f8',fitzpatrick_scale:!1,category:"symbols"},next_track_button:{keywords:["forward","next","blue-square"],char:'\u23ed',fitzpatrick_scale:!1,category:"symbols"},stop_button:{keywords:["blue-square"],char:'\u23f9',fitzpatrick_scale:!1,category:"symbols"},record_button:{keywords:["blue-square"],char:'\u23fa',fitzpatrick_scale:!1,category:"symbols"},play_or_pause_button:{keywords:["blue-square","play","pause"],char:'\u23ef',fitzpatrick_scale:!1,category:"symbols"},previous_track_button:{keywords:["backward"],char:'\u23ee',fitzpatrick_scale:!1,category:"symbols"},fast_forward:{keywords:["blue-square","play","speed","continue"],char:'\u23e9',fitzpatrick_scale:!1,category:"symbols"},rewind:{keywords:["play","blue-square"],char:'\u23ea',fitzpatrick_scale:!1,category:"symbols"},twisted_rightwards_arrows:{keywords:["blue-square","shuffle","music","random"],char:'\u{1f500}',fitzpatrick_scale:!1,category:"symbols"},repeat:{keywords:["loop","record"],char:'\u{1f501}',fitzpatrick_scale:!1,category:"symbols"},repeat_one:{keywords:["blue-square","loop"],char:'\u{1f502}',fitzpatrick_scale:!1,category:"symbols"},arrow_backward:{keywords:["blue-square","left","direction"],char:'\u25c0\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_up_small:{keywords:["blue-square","triangle","direction","point","forward","top"],char:'\u{1f53c}',fitzpatrick_scale:!1,category:"symbols"},arrow_down_small:{keywords:["blue-square","direction","bottom"],char:'\u{1f53d}',fitzpatrick_scale:!1,category:"symbols"},arrow_double_up:{keywords:["blue-square","direction","top"],char:'\u23eb',fitzpatrick_scale:!1,category:"symbols"},arrow_double_down:{keywords:["blue-square","direction","bottom"],char:'\u23ec',fitzpatrick_scale:!1,category:"symbols"},arrow_right:{keywords:["blue-square","next"],char:'\u27a1\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_left:{keywords:["blue-square","previous","back"],char:'\u2b05\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_up:{keywords:["blue-square","continue","top","direction"],char:'\u2b06\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_down:{keywords:["blue-square","direction","bottom"],char:'\u2b07\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_upper_right:{keywords:["blue-square","point","direction","diagonal","northeast"],char:'\u2197\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_lower_right:{keywords:["blue-square","direction","diagonal","southeast"],char:'\u2198\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_lower_left:{keywords:["blue-square","direction","diagonal","southwest"],char:'\u2199\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_upper_left:{keywords:["blue-square","point","direction","diagonal","northwest"],char:'\u2196\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_up_down:{keywords:["blue-square","direction","way","vertical"],char:'\u2195\ufe0f',fitzpatrick_scale:!1,category:"symbols"},left_right_arrow:{keywords:["shape","direction","horizontal","sideways"],char:'\u2194\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrows_counterclockwise:{keywords:["blue-square","sync","cycle"],char:'\u{1f504}',fitzpatrick_scale:!1,category:"symbols"},arrow_right_hook:{keywords:["blue-square","return","rotate","direction"],char:'\u21aa\ufe0f',fitzpatrick_scale:!1,category:"symbols"},leftwards_arrow_with_hook:{keywords:["back","return","blue-square","undo","enter"],char:'\u21a9\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_heading_up:{keywords:["blue-square","direction","top"],char:'\u2934\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrow_heading_down:{keywords:["blue-square","direction","bottom"],char:'\u2935\ufe0f',fitzpatrick_scale:!1,category:"symbols"},hash:{keywords:["symbol","blue-square","twitter"],char:'#\ufe0f\u20e3',fitzpatrick_scale:!1,category:"symbols"},information_source:{keywords:["blue-square","alphabet","letter"],char:'\u2139\ufe0f',fitzpatrick_scale:!1,category:"symbols"},abc:{keywords:["blue-square","alphabet"],char:'\u{1f524}',fitzpatrick_scale:!1,category:"symbols"},abcd:{keywords:["blue-square","alphabet"],char:'\u{1f521}',fitzpatrick_scale:!1,category:"symbols"},capital_abcd:{keywords:["alphabet","words","blue-square"],char:'\u{1f520}',fitzpatrick_scale:!1,category:"symbols"},symbols:{keywords:["blue-square","music","note","ampersand","percent","glyphs","characters"],char:'\u{1f523}',fitzpatrick_scale:!1,category:"symbols"},musical_note:{keywords:["score","tone","sound"],char:'\u{1f3b5}',fitzpatrick_scale:!1,category:"symbols"},notes:{keywords:["music","score"],char:'\u{1f3b6}',fitzpatrick_scale:!1,category:"symbols"},wavy_dash:{keywords:["draw","line","moustache","mustache","squiggle","scribble"],char:'\u3030\ufe0f',fitzpatrick_scale:!1,category:"symbols"},curly_loop:{keywords:["scribble","draw","shape","squiggle"],char:'\u27b0',fitzpatrick_scale:!1,category:"symbols"},heavy_check_mark:{keywords:["ok","nike","answer","yes","tick"],char:'\u2714\ufe0f',fitzpatrick_scale:!1,category:"symbols"},arrows_clockwise:{keywords:["sync","cycle","round","repeat"],char:'\u{1f503}',fitzpatrick_scale:!1,category:"symbols"},heavy_plus_sign:{keywords:["math","calculation","addition","more","increase"],char:'\u2795',fitzpatrick_scale:!1,category:"symbols"},heavy_minus_sign:{keywords:["math","calculation","subtract","less"],char:'\u2796',fitzpatrick_scale:!1,category:"symbols"},heavy_division_sign:{keywords:["divide","math","calculation"],char:'\u2797',fitzpatrick_scale:!1,category:"symbols"},heavy_multiplication_x:{keywords:["math","calculation"],char:'\u2716\ufe0f',fitzpatrick_scale:!1,category:"symbols"},infinity:{keywords:["forever"],char:'\u267e',fitzpatrick_scale:!1,category:"symbols"},heavy_dollar_sign:{keywords:["money","sales","payment","currency","buck"],char:'\u{1f4b2}',fitzpatrick_scale:!1,category:"symbols"},currency_exchange:{keywords:["money","sales","dollar","travel"],char:'\u{1f4b1}',fitzpatrick_scale:!1,category:"symbols"},copyright:{keywords:["ip","license","circle","law","legal"],char:'\xa9\ufe0f',fitzpatrick_scale:!1,category:"symbols"},registered:{keywords:["alphabet","circle"],char:'\xae\ufe0f',fitzpatrick_scale:!1,category:"symbols"},tm:{keywords:["trademark","brand","law","legal"],char:'\u2122\ufe0f',fitzpatrick_scale:!1,category:"symbols"},end:{keywords:["words","arrow"],char:'\u{1f51a}',fitzpatrick_scale:!1,category:"symbols"},back:{keywords:["arrow","words","return"],char:'\u{1f519}',fitzpatrick_scale:!1,category:"symbols"},on:{keywords:["arrow","words"],char:'\u{1f51b}',fitzpatrick_scale:!1,category:"symbols"},top:{keywords:["words","blue-square"],char:'\u{1f51d}',fitzpatrick_scale:!1,category:"symbols"},soon:{keywords:["arrow","words"],char:'\u{1f51c}',fitzpatrick_scale:!1,category:"symbols"},ballot_box_with_check:{keywords:["ok","agree","confirm","black-square","vote","election","yes","tick"],char:'\u2611\ufe0f',fitzpatrick_scale:!1,category:"symbols"},radio_button:{keywords:["input","old","music","circle"],char:'\u{1f518}',fitzpatrick_scale:!1,category:"symbols"},white_circle:{keywords:["shape","round"],char:'\u26aa',fitzpatrick_scale:!1,category:"symbols"},black_circle:{keywords:["shape","button","round"],char:'\u26ab',fitzpatrick_scale:!1,category:"symbols"},red_circle:{keywords:["shape","error","danger"],char:'\u{1f534}',fitzpatrick_scale:!1,category:"symbols"},large_blue_circle:{keywords:["shape","icon","button"],char:'\u{1f535}',fitzpatrick_scale:!1,category:"symbols"},small_orange_diamond:{keywords:["shape","jewel","gem"],char:'\u{1f538}',fitzpatrick_scale:!1,category:"symbols"},small_blue_diamond:{keywords:["shape","jewel","gem"],char:'\u{1f539}',fitzpatrick_scale:!1,category:"symbols"},large_orange_diamond:{keywords:["shape","jewel","gem"],char:'\u{1f536}',fitzpatrick_scale:!1,category:"symbols"},large_blue_diamond:{keywords:["shape","jewel","gem"],char:'\u{1f537}',fitzpatrick_scale:!1,category:"symbols"},small_red_triangle:{keywords:["shape","direction","up","top"],char:'\u{1f53a}',fitzpatrick_scale:!1,category:"symbols"},black_small_square:{keywords:["shape","icon"],char:'\u25aa\ufe0f',fitzpatrick_scale:!1,category:"symbols"},white_small_square:{keywords:["shape","icon"],char:'\u25ab\ufe0f',fitzpatrick_scale:!1,category:"symbols"},black_large_square:{keywords:["shape","icon","button"],char:'\u2b1b',fitzpatrick_scale:!1,category:"symbols"},white_large_square:{keywords:["shape","icon","stone","button"],char:'\u2b1c',fitzpatrick_scale:!1,category:"symbols"},small_red_triangle_down:{keywords:["shape","direction","bottom"],char:'\u{1f53b}',fitzpatrick_scale:!1,category:"symbols"},black_medium_square:{keywords:["shape","button","icon"],char:'\u25fc\ufe0f',fitzpatrick_scale:!1,category:"symbols"},white_medium_square:{keywords:["shape","stone","icon"],char:'\u25fb\ufe0f',fitzpatrick_scale:!1,category:"symbols"},black_medium_small_square:{keywords:["icon","shape","button"],char:'\u25fe',fitzpatrick_scale:!1,category:"symbols"},white_medium_small_square:{keywords:["shape","stone","icon","button"],char:'\u25fd',fitzpatrick_scale:!1,category:"symbols"},black_square_button:{keywords:["shape","input","frame"],char:'\u{1f532}',fitzpatrick_scale:!1,category:"symbols"},white_square_button:{keywords:["shape","input"],char:'\u{1f533}',fitzpatrick_scale:!1,category:"symbols"},speaker:{keywords:["sound","volume","silence","broadcast"],char:'\u{1f508}',fitzpatrick_scale:!1,category:"symbols"},sound:{keywords:["volume","speaker","broadcast"],char:'\u{1f509}',fitzpatrick_scale:!1,category:"symbols"},loud_sound:{keywords:["volume","noise","noisy","speaker","broadcast"],char:'\u{1f50a}',fitzpatrick_scale:!1,category:"symbols"},mute:{keywords:["sound","volume","silence","quiet"],char:'\u{1f507}',fitzpatrick_scale:!1,category:"symbols"},mega:{keywords:["sound","speaker","volume"],char:'\u{1f4e3}',fitzpatrick_scale:!1,category:"symbols"},loudspeaker:{keywords:["volume","sound"],char:'\u{1f4e2}',fitzpatrick_scale:!1,category:"symbols"},bell:{keywords:["sound","notification","christmas","xmas","chime"],char:'\u{1f514}',fitzpatrick_scale:!1,category:"symbols"},no_bell:{keywords:["sound","volume","mute","quiet","silent"],char:'\u{1f515}',fitzpatrick_scale:!1,category:"symbols"},black_joker:{keywords:["poker","cards","game","play","magic"],char:'\u{1f0cf}',fitzpatrick_scale:!1,category:"symbols"},mahjong:{keywords:["game","play","chinese","kanji"],char:'\u{1f004}',fitzpatrick_scale:!1,category:"symbols"},spades:{keywords:["poker","cards","suits","magic"],char:'\u2660\ufe0f',fitzpatrick_scale:!1,category:"symbols"},clubs:{keywords:["poker","cards","magic","suits"],char:'\u2663\ufe0f',fitzpatrick_scale:!1,category:"symbols"},hearts:{keywords:["poker","cards","magic","suits"],char:'\u2665\ufe0f',fitzpatrick_scale:!1,category:"symbols"},diamonds:{keywords:["poker","cards","magic","suits"],char:'\u2666\ufe0f',fitzpatrick_scale:!1,category:"symbols"},flower_playing_cards:{keywords:["game","sunset","red"],char:'\u{1f3b4}',fitzpatrick_scale:!1,category:"symbols"},thought_balloon:{keywords:["bubble","cloud","speech","thinking","dream"],char:'\u{1f4ad}',fitzpatrick_scale:!1,category:"symbols"},right_anger_bubble:{keywords:["caption","speech","thinking","mad"],char:'\u{1f5ef}',fitzpatrick_scale:!1,category:"symbols"},speech_balloon:{keywords:["bubble","words","message","talk","chatting"],char:'\u{1f4ac}',fitzpatrick_scale:!1,category:"symbols"},left_speech_bubble:{keywords:["words","message","talk","chatting"],char:'\u{1f5e8}',fitzpatrick_scale:!1,category:"symbols"},clock1:{keywords:["time","late","early","schedule"],char:'\u{1f550}',fitzpatrick_scale:!1,category:"symbols"},clock2:{keywords:["time","late","early","schedule"],char:'\u{1f551}',fitzpatrick_scale:!1,category:"symbols"},clock3:{keywords:["time","late","early","schedule"],char:'\u{1f552}',fitzpatrick_scale:!1,category:"symbols"},clock4:{keywords:["time","late","early","schedule"],char:'\u{1f553}',fitzpatrick_scale:!1,category:"symbols"},clock5:{keywords:["time","late","early","schedule"],char:'\u{1f554}',fitzpatrick_scale:!1,category:"symbols"},clock6:{keywords:["time","late","early","schedule","dawn","dusk"],char:'\u{1f555}',fitzpatrick_scale:!1,category:"symbols"},clock7:{keywords:["time","late","early","schedule"],char:'\u{1f556}',fitzpatrick_scale:!1,category:"symbols"},clock8:{keywords:["time","late","early","schedule"],char:'\u{1f557}',fitzpatrick_scale:!1,category:"symbols"},clock9:{keywords:["time","late","early","schedule"],char:'\u{1f558}',fitzpatrick_scale:!1,category:"symbols"},clock10:{keywords:["time","late","early","schedule"],char:'\u{1f559}',fitzpatrick_scale:!1,category:"symbols"},clock11:{keywords:["time","late","early","schedule"],char:'\u{1f55a}',fitzpatrick_scale:!1,category:"symbols"},clock12:{keywords:["time","noon","midnight","midday","late","early","schedule"],char:'\u{1f55b}',fitzpatrick_scale:!1,category:"symbols"},clock130:{keywords:["time","late","early","schedule"],char:'\u{1f55c}',fitzpatrick_scale:!1,category:"symbols"},clock230:{keywords:["time","late","early","schedule"],char:'\u{1f55d}',fitzpatrick_scale:!1,category:"symbols"},clock330:{keywords:["time","late","early","schedule"],char:'\u{1f55e}',fitzpatrick_scale:!1,category:"symbols"},clock430:{keywords:["time","late","early","schedule"],char:'\u{1f55f}',fitzpatrick_scale:!1,category:"symbols"},clock530:{keywords:["time","late","early","schedule"],char:'\u{1f560}',fitzpatrick_scale:!1,category:"symbols"},clock630:{keywords:["time","late","early","schedule"],char:'\u{1f561}',fitzpatrick_scale:!1,category:"symbols"},clock730:{keywords:["time","late","early","schedule"],char:'\u{1f562}',fitzpatrick_scale:!1,category:"symbols"},clock830:{keywords:["time","late","early","schedule"],char:'\u{1f563}',fitzpatrick_scale:!1,category:"symbols"},clock930:{keywords:["time","late","early","schedule"],char:'\u{1f564}',fitzpatrick_scale:!1,category:"symbols"},clock1030:{keywords:["time","late","early","schedule"],char:'\u{1f565}',fitzpatrick_scale:!1,category:"symbols"},clock1130:{keywords:["time","late","early","schedule"],char:'\u{1f566}',fitzpatrick_scale:!1,category:"symbols"},clock1230:{keywords:["time","late","early","schedule"],char:'\u{1f567}',fitzpatrick_scale:!1,category:"symbols"},afghanistan:{keywords:["af","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},aland_islands:{keywords:["\xc5land","islands","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1fd}',fitzpatrick_scale:!1,category:"flags"},albania:{keywords:["al","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},algeria:{keywords:["dz","flag","nation","country","banner"],char:'\u{1f1e9}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},american_samoa:{keywords:["american","ws","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},andorra:{keywords:["ad","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},angola:{keywords:["ao","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},anguilla:{keywords:["ai","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},antarctica:{keywords:["aq","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1f6}',fitzpatrick_scale:!1,category:"flags"},antigua_barbuda:{keywords:["antigua","barbuda","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},argentina:{keywords:["ar","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},armenia:{keywords:["am","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},aruba:{keywords:["aw","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},australia:{keywords:["au","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},austria:{keywords:["at","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},azerbaijan:{keywords:["az","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},bahamas:{keywords:["bs","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},bahrain:{keywords:["bh","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},bangladesh:{keywords:["bd","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},barbados:{keywords:["bb","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1e7}',fitzpatrick_scale:!1,category:"flags"},belarus:{keywords:["by","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},belgium:{keywords:["be","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},belize:{keywords:["bz","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},benin:{keywords:["bj","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1ef}',fitzpatrick_scale:!1,category:"flags"},bermuda:{keywords:["bm","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},bhutan:{keywords:["bt","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},bolivia:{keywords:["bo","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},caribbean_netherlands:{keywords:["bonaire","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f6}',fitzpatrick_scale:!1,category:"flags"},bosnia_herzegovina:{keywords:["bosnia","herzegovina","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},botswana:{keywords:["bw","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},brazil:{keywords:["br","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},british_indian_ocean_territory:{keywords:["british","indian","ocean","territory","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},british_virgin_islands:{keywords:["british","virgin","islands","bvi","flag","nation","country","banner"],char:'\u{1f1fb}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},brunei:{keywords:["bn","darussalam","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},bulgaria:{keywords:["bg","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},burkina_faso:{keywords:["burkina","faso","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},burundi:{keywords:["bi","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},cape_verde:{keywords:["cabo","verde","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1fb}',fitzpatrick_scale:!1,category:"flags"},cambodia:{keywords:["kh","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},cameroon:{keywords:["cm","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},canada:{keywords:["ca","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},canary_islands:{keywords:["canary","islands","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},cayman_islands:{keywords:["cayman","islands","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},central_african_republic:{keywords:["central","african","republic","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},chad:{keywords:["td","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},chile:{keywords:["flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},cn:{keywords:["china","chinese","prc","flag","country","nation","banner"],char:'\u{1f1e8}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},christmas_island:{keywords:["christmas","island","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1fd}',fitzpatrick_scale:!1,category:"flags"},cocos_islands:{keywords:["cocos","keeling","islands","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},colombia:{keywords:["co","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},comoros:{keywords:["km","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},congo_brazzaville:{keywords:["congo","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},congo_kinshasa:{keywords:["congo","democratic","republic","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},cook_islands:{keywords:["cook","islands","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},costa_rica:{keywords:["costa","rica","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},croatia:{keywords:["hr","flag","nation","country","banner"],char:'\u{1f1ed}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},cuba:{keywords:["cu","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},curacao:{keywords:["cura\xe7ao","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},cyprus:{keywords:["cy","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},czech_republic:{keywords:["cz","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},denmark:{keywords:["dk","flag","nation","country","banner"],char:'\u{1f1e9}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},djibouti:{keywords:["dj","flag","nation","country","banner"],char:'\u{1f1e9}\u{1f1ef}',fitzpatrick_scale:!1,category:"flags"},dominica:{keywords:["dm","flag","nation","country","banner"],char:'\u{1f1e9}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},dominican_republic:{keywords:["dominican","republic","flag","nation","country","banner"],char:'\u{1f1e9}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},ecuador:{keywords:["ec","flag","nation","country","banner"],char:'\u{1f1ea}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},egypt:{keywords:["eg","flag","nation","country","banner"],char:'\u{1f1ea}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},el_salvador:{keywords:["el","salvador","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1fb}',fitzpatrick_scale:!1,category:"flags"},equatorial_guinea:{keywords:["equatorial","gn","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f6}',fitzpatrick_scale:!1,category:"flags"},eritrea:{keywords:["er","flag","nation","country","banner"],char:'\u{1f1ea}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},estonia:{keywords:["ee","flag","nation","country","banner"],char:'\u{1f1ea}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},ethiopia:{keywords:["et","flag","nation","country","banner"],char:'\u{1f1ea}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},eu:{keywords:["european","union","flag","banner"],char:'\u{1f1ea}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},falkland_islands:{keywords:["falkland","islands","malvinas","flag","nation","country","banner"],char:'\u{1f1eb}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},faroe_islands:{keywords:["faroe","islands","flag","nation","country","banner"],char:'\u{1f1eb}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},fiji:{keywords:["fj","flag","nation","country","banner"],char:'\u{1f1eb}\u{1f1ef}',fitzpatrick_scale:!1,category:"flags"},finland:{keywords:["fi","flag","nation","country","banner"],char:'\u{1f1eb}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},fr:{keywords:["banner","flag","nation","france","french","country"],char:'\u{1f1eb}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},french_guiana:{keywords:["french","guiana","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},french_polynesia:{keywords:["french","polynesia","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},french_southern_territories:{keywords:["french","southern","territories","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},gabon:{keywords:["ga","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},gambia:{keywords:["gm","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},georgia:{keywords:["ge","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},de:{keywords:["german","nation","flag","country","banner"],char:'\u{1f1e9}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},ghana:{keywords:["gh","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},gibraltar:{keywords:["gi","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},greece:{keywords:["gr","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},greenland:{keywords:["gl","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},grenada:{keywords:["gd","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},guadeloupe:{keywords:["gp","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f5}',fitzpatrick_scale:!1,category:"flags"},guam:{keywords:["gu","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},guatemala:{keywords:["gt","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},guernsey:{keywords:["gg","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},guinea:{keywords:["gn","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},guinea_bissau:{keywords:["gw","bissau","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},guyana:{keywords:["gy","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},haiti:{keywords:["ht","flag","nation","country","banner"],char:'\u{1f1ed}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},honduras:{keywords:["hn","flag","nation","country","banner"],char:'\u{1f1ed}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},hong_kong:{keywords:["hong","kong","flag","nation","country","banner"],char:'\u{1f1ed}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},hungary:{keywords:["hu","flag","nation","country","banner"],char:'\u{1f1ed}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},iceland:{keywords:["is","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},india:{keywords:["in","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},indonesia:{keywords:["flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},iran:{keywords:["iran,","islamic","republic","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},iraq:{keywords:["iq","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f6}',fitzpatrick_scale:!1,category:"flags"},ireland:{keywords:["ie","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},isle_of_man:{keywords:["isle","man","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},israel:{keywords:["il","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},it:{keywords:["italy","flag","nation","country","banner"],char:'\u{1f1ee}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},cote_divoire:{keywords:["ivory","coast","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},jamaica:{keywords:["jm","flag","nation","country","banner"],char:'\u{1f1ef}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},jp:{keywords:["japanese","nation","flag","country","banner"],char:'\u{1f1ef}\u{1f1f5}',fitzpatrick_scale:!1,category:"flags"},jersey:{keywords:["je","flag","nation","country","banner"],char:'\u{1f1ef}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},jordan:{keywords:["jo","flag","nation","country","banner"],char:'\u{1f1ef}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},kazakhstan:{keywords:["kz","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},kenya:{keywords:["ke","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},kiribati:{keywords:["ki","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},kosovo:{keywords:["xk","flag","nation","country","banner"],char:'\u{1f1fd}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},kuwait:{keywords:["kw","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},kyrgyzstan:{keywords:["kg","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},laos:{keywords:["lao","democratic","republic","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},latvia:{keywords:["lv","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1fb}',fitzpatrick_scale:!1,category:"flags"},lebanon:{keywords:["lb","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1e7}',fitzpatrick_scale:!1,category:"flags"},lesotho:{keywords:["ls","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},liberia:{keywords:["lr","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},libya:{keywords:["ly","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},liechtenstein:{keywords:["li","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},lithuania:{keywords:["lt","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},luxembourg:{keywords:["lu","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},macau:{keywords:["macao","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},macedonia:{keywords:["macedonia,","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},madagascar:{keywords:["mg","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},malawi:{keywords:["mw","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},malaysia:{keywords:["my","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},maldives:{keywords:["mv","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1fb}',fitzpatrick_scale:!1,category:"flags"},mali:{keywords:["ml","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},malta:{keywords:["mt","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},marshall_islands:{keywords:["marshall","islands","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},martinique:{keywords:["mq","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f6}',fitzpatrick_scale:!1,category:"flags"},mauritania:{keywords:["mr","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},mauritius:{keywords:["mu","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},mayotte:{keywords:["yt","flag","nation","country","banner"],char:'\u{1f1fe}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},mexico:{keywords:["mx","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1fd}',fitzpatrick_scale:!1,category:"flags"},micronesia:{keywords:["micronesia,","federated","states","flag","nation","country","banner"],char:'\u{1f1eb}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},moldova:{keywords:["moldova,","republic","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},monaco:{keywords:["mc","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},mongolia:{keywords:["mn","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},montenegro:{keywords:["me","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},montserrat:{keywords:["ms","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},morocco:{keywords:["ma","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},mozambique:{keywords:["mz","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},myanmar:{keywords:["mm","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},namibia:{keywords:["na","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},nauru:{keywords:["nr","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},nepal:{keywords:["np","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1f5}',fitzpatrick_scale:!1,category:"flags"},netherlands:{keywords:["nl","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},new_caledonia:{keywords:["new","caledonia","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},new_zealand:{keywords:["new","zealand","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},nicaragua:{keywords:["ni","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},niger:{keywords:["ne","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},nigeria:{keywords:["flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},niue:{keywords:["nu","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},norfolk_island:{keywords:["norfolk","island","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},northern_mariana_islands:{keywords:["northern","mariana","islands","flag","nation","country","banner"],char:'\u{1f1f2}\u{1f1f5}',fitzpatrick_scale:!1,category:"flags"},north_korea:{keywords:["north","korea","nation","flag","country","banner"],char:'\u{1f1f0}\u{1f1f5}',fitzpatrick_scale:!1,category:"flags"},norway:{keywords:["no","flag","nation","country","banner"],char:'\u{1f1f3}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},oman:{keywords:["om_symbol","flag","nation","country","banner"],char:'\u{1f1f4}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},pakistan:{keywords:["pk","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},palau:{keywords:["pw","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},palestinian_territories:{keywords:["palestine","palestinian","territories","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},panama:{keywords:["pa","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},papua_new_guinea:{keywords:["papua","new","guinea","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},paraguay:{keywords:["py","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},peru:{keywords:["pe","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},philippines:{keywords:["ph","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},pitcairn_islands:{keywords:["pitcairn","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},poland:{keywords:["pl","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},portugal:{keywords:["pt","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},puerto_rico:{keywords:["puerto","rico","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},qatar:{keywords:["qa","flag","nation","country","banner"],char:'\u{1f1f6}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},reunion:{keywords:["r\xe9union","flag","nation","country","banner"],char:'\u{1f1f7}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},romania:{keywords:["ro","flag","nation","country","banner"],char:'\u{1f1f7}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},ru:{keywords:["russian","federation","flag","nation","country","banner"],char:'\u{1f1f7}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},rwanda:{keywords:["rw","flag","nation","country","banner"],char:'\u{1f1f7}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},st_barthelemy:{keywords:["saint","barth\xe9lemy","flag","nation","country","banner"],char:'\u{1f1e7}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},st_helena:{keywords:["saint","helena","ascension","tristan","cunha","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},st_kitts_nevis:{keywords:["saint","kitts","nevis","flag","nation","country","banner"],char:'\u{1f1f0}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},st_lucia:{keywords:["saint","lucia","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},st_pierre_miquelon:{keywords:["saint","pierre","miquelon","flag","nation","country","banner"],char:'\u{1f1f5}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},st_vincent_grenadines:{keywords:["saint","vincent","grenadines","flag","nation","country","banner"],char:'\u{1f1fb}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},samoa:{keywords:["ws","flag","nation","country","banner"],char:'\u{1f1fc}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},san_marino:{keywords:["san","marino","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},sao_tome_principe:{keywords:["sao","tome","principe","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},saudi_arabia:{keywords:["flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},senegal:{keywords:["sn","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},serbia:{keywords:["rs","flag","nation","country","banner"],char:'\u{1f1f7}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},seychelles:{keywords:["sc","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},sierra_leone:{keywords:["sierra","leone","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},singapore:{keywords:["sg","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},sint_maarten:{keywords:["sint","maarten","dutch","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1fd}',fitzpatrick_scale:!1,category:"flags"},slovakia:{keywords:["sk","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},slovenia:{keywords:["si","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},solomon_islands:{keywords:["solomon","islands","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1e7}',fitzpatrick_scale:!1,category:"flags"},somalia:{keywords:["so","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},south_africa:{keywords:["south","africa","flag","nation","country","banner"],char:'\u{1f1ff}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},south_georgia_south_sandwich_islands:{keywords:["south","georgia","sandwich","islands","flag","nation","country","banner"],char:'\u{1f1ec}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},kr:{keywords:["south","korea","nation","flag","country","banner"],char:'\u{1f1f0}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},south_sudan:{keywords:["south","sd","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},es:{keywords:["spain","flag","nation","country","banner"],char:'\u{1f1ea}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},sri_lanka:{keywords:["sri","lanka","flag","nation","country","banner"],char:'\u{1f1f1}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},sudan:{keywords:["sd","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1e9}',fitzpatrick_scale:!1,category:"flags"},suriname:{keywords:["sr","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},swaziland:{keywords:["sz","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},sweden:{keywords:["se","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},switzerland:{keywords:["ch","flag","nation","country","banner"],char:'\u{1f1e8}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},syria:{keywords:["syrian","arab","republic","flag","nation","country","banner"],char:'\u{1f1f8}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},taiwan:{keywords:["tw","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},tajikistan:{keywords:["tj","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1ef}',fitzpatrick_scale:!1,category:"flags"},tanzania:{keywords:["tanzania,","united","republic","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},thailand:{keywords:["th","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},timor_leste:{keywords:["timor","leste","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1f1}',fitzpatrick_scale:!1,category:"flags"},togo:{keywords:["tg","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},tokelau:{keywords:["tk","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1f0}',fitzpatrick_scale:!1,category:"flags"},tonga:{keywords:["to","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1f4}',fitzpatrick_scale:!1,category:"flags"},trinidad_tobago:{keywords:["trinidad","tobago","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1f9}',fitzpatrick_scale:!1,category:"flags"},tunisia:{keywords:["tn","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},tr:{keywords:["turkey","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1f7}',fitzpatrick_scale:!1,category:"flags"},turkmenistan:{keywords:["flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},turks_caicos_islands:{keywords:["turks","caicos","islands","flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1e8}',fitzpatrick_scale:!1,category:"flags"},tuvalu:{keywords:["flag","nation","country","banner"],char:'\u{1f1f9}\u{1f1fb}',fitzpatrick_scale:!1,category:"flags"},uganda:{keywords:["ug","flag","nation","country","banner"],char:'\u{1f1fa}\u{1f1ec}',fitzpatrick_scale:!1,category:"flags"},ukraine:{keywords:["ua","flag","nation","country","banner"],char:'\u{1f1fa}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},united_arab_emirates:{keywords:["united","arab","emirates","flag","nation","country","banner"],char:'\u{1f1e6}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},uk:{keywords:["united","kingdom","great","britain","northern","ireland","flag","nation","country","banner","british","UK","english","england","union jack"],char:'\u{1f1ec}\u{1f1e7}',fitzpatrick_scale:!1,category:"flags"},england:{keywords:["flag","english"],char:'\u{1f3f4}\u{e0067}\u{e0062}\u{e0065}\u{e006e}\u{e0067}\u{e007f}',fitzpatrick_scale:!1,category:"flags"},scotland:{keywords:["flag","scottish"],char:'\u{1f3f4}\u{e0067}\u{e0062}\u{e0073}\u{e0063}\u{e0074}\u{e007f}',fitzpatrick_scale:!1,category:"flags"},wales:{keywords:["flag","welsh"],char:'\u{1f3f4}\u{e0067}\u{e0062}\u{e0077}\u{e006c}\u{e0073}\u{e007f}',fitzpatrick_scale:!1,category:"flags"},us:{keywords:["united","states","america","flag","nation","country","banner"],char:'\u{1f1fa}\u{1f1f8}',fitzpatrick_scale:!1,category:"flags"},us_virgin_islands:{keywords:["virgin","islands","us","flag","nation","country","banner"],char:'\u{1f1fb}\u{1f1ee}',fitzpatrick_scale:!1,category:"flags"},uruguay:{keywords:["uy","flag","nation","country","banner"],char:'\u{1f1fa}\u{1f1fe}',fitzpatrick_scale:!1,category:"flags"},uzbekistan:{keywords:["uz","flag","nation","country","banner"],char:'\u{1f1fa}\u{1f1ff}',fitzpatrick_scale:!1,category:"flags"},vanuatu:{keywords:["vu","flag","nation","country","banner"],char:'\u{1f1fb}\u{1f1fa}',fitzpatrick_scale:!1,category:"flags"},vatican_city:{keywords:["vatican","city","flag","nation","country","banner"],char:'\u{1f1fb}\u{1f1e6}',fitzpatrick_scale:!1,category:"flags"},venezuela:{keywords:["ve","bolivarian","republic","flag","nation","country","banner"],char:'\u{1f1fb}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},vietnam:{keywords:["viet","nam","flag","nation","country","banner"],char:'\u{1f1fb}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},wallis_futuna:{keywords:["wallis","futuna","flag","nation","country","banner"],char:'\u{1f1fc}\u{1f1eb}',fitzpatrick_scale:!1,category:"flags"},western_sahara:{keywords:["western","sahara","flag","nation","country","banner"],char:'\u{1f1ea}\u{1f1ed}',fitzpatrick_scale:!1,category:"flags"},yemen:{keywords:["ye","flag","nation","country","banner"],char:'\u{1f1fe}\u{1f1ea}',fitzpatrick_scale:!1,category:"flags"},zambia:{keywords:["zm","flag","nation","country","banner"],char:'\u{1f1ff}\u{1f1f2}',fitzpatrick_scale:!1,category:"flags"},zimbabwe:{keywords:["zw","flag","nation","country","banner"],char:'\u{1f1ff}\u{1f1fc}',fitzpatrick_scale:!1,category:"flags"},united_nations:{keywords:["un","flag","banner"],char:'\u{1f1fa}\u{1f1f3}',fitzpatrick_scale:!1,category:"flags"},pirate_flag:{keywords:["skull","crossbones","flag","banner"],char:'\u{1f3f4}\u200d\u2620\ufe0f',fitzpatrick_scale:!1,category:"flags"}}); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/emoticons/js/emojis.js b/public/plugins/tinymce/plugins/emoticons/js/emojis.js new file mode 100644 index 000000000..88455e9a4 --- /dev/null +++ b/public/plugins/tinymce/plugins/emoticons/js/emojis.js @@ -0,0 +1 @@ +window.tinymce.Resource.add("tinymce.plugins.emoticons",{grinning:{keywords:["face","smile","happy","joy",":D","grin"],char:"😀",fitzpatrick_scale:false,category:"people"},grimacing:{keywords:["face","grimace","teeth"],char:"😬",fitzpatrick_scale:false,category:"people"},grin:{keywords:["face","happy","smile","joy","kawaii"],char:"😁",fitzpatrick_scale:false,category:"people"},joy:{keywords:["face","cry","tears","weep","happy","happytears","haha"],char:"😂",fitzpatrick_scale:false,category:"people"},rofl:{keywords:["face","rolling","floor","laughing","lol","haha"],char:"🤣",fitzpatrick_scale:false,category:"people"},partying:{keywords:["face","celebration","woohoo"],char:"🥳",fitzpatrick_scale:false,category:"people"},smiley:{keywords:["face","happy","joy","haha",":D",":)","smile","funny"],char:"😃",fitzpatrick_scale:false,category:"people"},smile:{keywords:["face","happy","joy","funny","haha","laugh","like",":D",":)"],char:"😄",fitzpatrick_scale:false,category:"people"},sweat_smile:{keywords:["face","hot","happy","laugh","sweat","smile","relief"],char:"😅",fitzpatrick_scale:false,category:"people"},laughing:{keywords:["happy","joy","lol","satisfied","haha","face","glad","XD","laugh"],char:"😆",fitzpatrick_scale:false,category:"people"},innocent:{keywords:["face","angel","heaven","halo"],char:"😇",fitzpatrick_scale:false,category:"people"},wink:{keywords:["face","happy","mischievous","secret",";)","smile","eye"],char:"😉",fitzpatrick_scale:false,category:"people"},blush:{keywords:["face","smile","happy","flushed","crush","embarrassed","shy","joy"],char:"😊",fitzpatrick_scale:false,category:"people"},slightly_smiling_face:{keywords:["face","smile"],char:"🙂",fitzpatrick_scale:false,category:"people"},upside_down_face:{keywords:["face","flipped","silly","smile"],char:"🙃",fitzpatrick_scale:false,category:"people"},relaxed:{keywords:["face","blush","massage","happiness"],char:"☺️",fitzpatrick_scale:false,category:"people"},yum:{keywords:["happy","joy","tongue","smile","face","silly","yummy","nom","delicious","savouring"],char:"😋",fitzpatrick_scale:false,category:"people"},relieved:{keywords:["face","relaxed","phew","massage","happiness"],char:"😌",fitzpatrick_scale:false,category:"people"},heart_eyes:{keywords:["face","love","like","affection","valentines","infatuation","crush","heart"],char:"😍",fitzpatrick_scale:false,category:"people"},smiling_face_with_three_hearts:{keywords:["face","love","like","affection","valentines","infatuation","crush","hearts","adore"],char:"🥰",fitzpatrick_scale:false,category:"people"},kissing_heart:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:"😘",fitzpatrick_scale:false,category:"people"},kissing:{keywords:["love","like","face","3","valentines","infatuation","kiss"],char:"😗",fitzpatrick_scale:false,category:"people"},kissing_smiling_eyes:{keywords:["face","affection","valentines","infatuation","kiss"],char:"😙",fitzpatrick_scale:false,category:"people"},kissing_closed_eyes:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:"😚",fitzpatrick_scale:false,category:"people"},stuck_out_tongue_winking_eye:{keywords:["face","prank","childish","playful","mischievous","smile","wink","tongue"],char:"😜",fitzpatrick_scale:false,category:"people"},zany:{keywords:["face","goofy","crazy"],char:"🤪",fitzpatrick_scale:false,category:"people"},raised_eyebrow:{keywords:["face","distrust","scepticism","disapproval","disbelief","surprise"],char:"🤨",fitzpatrick_scale:false,category:"people"},monocle:{keywords:["face","stuffy","wealthy"],char:"🧐",fitzpatrick_scale:false,category:"people"},stuck_out_tongue_closed_eyes:{keywords:["face","prank","playful","mischievous","smile","tongue"],char:"😝",fitzpatrick_scale:false,category:"people"},stuck_out_tongue:{keywords:["face","prank","childish","playful","mischievous","smile","tongue"],char:"😛",fitzpatrick_scale:false,category:"people"},money_mouth_face:{keywords:["face","rich","dollar","money"],char:"🤑",fitzpatrick_scale:false,category:"people"},nerd_face:{keywords:["face","nerdy","geek","dork"],char:"🤓",fitzpatrick_scale:false,category:"people"},sunglasses:{keywords:["face","cool","smile","summer","beach","sunglass"],char:"😎",fitzpatrick_scale:false,category:"people"},star_struck:{keywords:["face","smile","starry","eyes","grinning"],char:"🤩",fitzpatrick_scale:false,category:"people"},clown_face:{keywords:["face"],char:"🤡",fitzpatrick_scale:false,category:"people"},cowboy_hat_face:{keywords:["face","cowgirl","hat"],char:"🤠",fitzpatrick_scale:false,category:"people"},hugs:{keywords:["face","smile","hug"],char:"🤗",fitzpatrick_scale:false,category:"people"},smirk:{keywords:["face","smile","mean","prank","smug","sarcasm"],char:"😏",fitzpatrick_scale:false,category:"people"},no_mouth:{keywords:["face","hellokitty"],char:"😶",fitzpatrick_scale:false,category:"people"},neutral_face:{keywords:["indifference","meh",":|","neutral"],char:"😐",fitzpatrick_scale:false,category:"people"},expressionless:{keywords:["face","indifferent","-_-","meh","deadpan"],char:"😑",fitzpatrick_scale:false,category:"people"},unamused:{keywords:["indifference","bored","straight face","serious","sarcasm","unimpressed","skeptical","dubious","side_eye"],char:"😒",fitzpatrick_scale:false,category:"people"},roll_eyes:{keywords:["face","eyeroll","frustrated"],char:"🙄",fitzpatrick_scale:false,category:"people"},thinking:{keywords:["face","hmmm","think","consider"],char:"🤔",fitzpatrick_scale:false,category:"people"},lying_face:{keywords:["face","lie","pinocchio"],char:"🤥",fitzpatrick_scale:false,category:"people"},hand_over_mouth:{keywords:["face","whoops","shock","surprise"],char:"🤭",fitzpatrick_scale:false,category:"people"},shushing:{keywords:["face","quiet","shhh"],char:"🤫",fitzpatrick_scale:false,category:"people"},symbols_over_mouth:{keywords:["face","swearing","cursing","cussing","profanity","expletive"],char:"🤬",fitzpatrick_scale:false,category:"people"},exploding_head:{keywords:["face","shocked","mind","blown"],char:"🤯",fitzpatrick_scale:false,category:"people"},flushed:{keywords:["face","blush","shy","flattered"],char:"😳",fitzpatrick_scale:false,category:"people"},disappointed:{keywords:["face","sad","upset","depressed",":("],char:"😞",fitzpatrick_scale:false,category:"people"},worried:{keywords:["face","concern","nervous",":("],char:"😟",fitzpatrick_scale:false,category:"people"},angry:{keywords:["mad","face","annoyed","frustrated"],char:"😠",fitzpatrick_scale:false,category:"people"},rage:{keywords:["angry","mad","hate","despise"],char:"😡",fitzpatrick_scale:false,category:"people"},pensive:{keywords:["face","sad","depressed","upset"],char:"😔",fitzpatrick_scale:false,category:"people"},confused:{keywords:["face","indifference","huh","weird","hmmm",":/"],char:"😕",fitzpatrick_scale:false,category:"people"},slightly_frowning_face:{keywords:["face","frowning","disappointed","sad","upset"],char:"🙁",fitzpatrick_scale:false,category:"people"},frowning_face:{keywords:["face","sad","upset","frown"],char:"☹",fitzpatrick_scale:false,category:"people"},persevere:{keywords:["face","sick","no","upset","oops"],char:"😣",fitzpatrick_scale:false,category:"people"},confounded:{keywords:["face","confused","sick","unwell","oops",":S"],char:"😖",fitzpatrick_scale:false,category:"people"},tired_face:{keywords:["sick","whine","upset","frustrated"],char:"😫",fitzpatrick_scale:false,category:"people"},weary:{keywords:["face","tired","sleepy","sad","frustrated","upset"],char:"😩",fitzpatrick_scale:false,category:"people"},pleading:{keywords:["face","begging","mercy"],char:"🥺",fitzpatrick_scale:false,category:"people"},triumph:{keywords:["face","gas","phew","proud","pride"],char:"😤",fitzpatrick_scale:false,category:"people"},open_mouth:{keywords:["face","surprise","impressed","wow","whoa",":O"],char:"😮",fitzpatrick_scale:false,category:"people"},scream:{keywords:["face","munch","scared","omg"],char:"😱",fitzpatrick_scale:false,category:"people"},fearful:{keywords:["face","scared","terrified","nervous","oops","huh"],char:"😨",fitzpatrick_scale:false,category:"people"},cold_sweat:{keywords:["face","nervous","sweat"],char:"😰",fitzpatrick_scale:false,category:"people"},hushed:{keywords:["face","woo","shh"],char:"😯",fitzpatrick_scale:false,category:"people"},frowning:{keywords:["face","aw","what"],char:"😦",fitzpatrick_scale:false,category:"people"},anguished:{keywords:["face","stunned","nervous"],char:"😧",fitzpatrick_scale:false,category:"people"},cry:{keywords:["face","tears","sad","depressed","upset",":'("],char:"😢",fitzpatrick_scale:false,category:"people"},disappointed_relieved:{keywords:["face","phew","sweat","nervous"],char:"😥",fitzpatrick_scale:false,category:"people"},drooling_face:{keywords:["face"],char:"🤤",fitzpatrick_scale:false,category:"people"},sleepy:{keywords:["face","tired","rest","nap"],char:"😪",fitzpatrick_scale:false,category:"people"},sweat:{keywords:["face","hot","sad","tired","exercise"],char:"😓",fitzpatrick_scale:false,category:"people"},hot:{keywords:["face","feverish","heat","red","sweating"],char:"🥵",fitzpatrick_scale:false,category:"people"},cold:{keywords:["face","blue","freezing","frozen","frostbite","icicles"],char:"🥶",fitzpatrick_scale:false,category:"people"},sob:{keywords:["face","cry","tears","sad","upset","depressed"],char:"😭",fitzpatrick_scale:false,category:"people"},dizzy_face:{keywords:["spent","unconscious","xox","dizzy"],char:"😵",fitzpatrick_scale:false,category:"people"},astonished:{keywords:["face","xox","surprised","poisoned"],char:"😲",fitzpatrick_scale:false,category:"people"},zipper_mouth_face:{keywords:["face","sealed","zipper","secret"],char:"🤐",fitzpatrick_scale:false,category:"people"},nauseated_face:{keywords:["face","vomit","gross","green","sick","throw up","ill"],char:"🤢",fitzpatrick_scale:false,category:"people"},sneezing_face:{keywords:["face","gesundheit","sneeze","sick","allergy"],char:"🤧",fitzpatrick_scale:false,category:"people"},vomiting:{keywords:["face","sick"],char:"🤮",fitzpatrick_scale:false,category:"people"},mask:{keywords:["face","sick","ill","disease"],char:"😷",fitzpatrick_scale:false,category:"people"},face_with_thermometer:{keywords:["sick","temperature","thermometer","cold","fever"],char:"🤒",fitzpatrick_scale:false,category:"people"},face_with_head_bandage:{keywords:["injured","clumsy","bandage","hurt"],char:"🤕",fitzpatrick_scale:false,category:"people"},woozy:{keywords:["face","dizzy","intoxicated","tipsy","wavy"],char:"🥴",fitzpatrick_scale:false,category:"people"},sleeping:{keywords:["face","tired","sleepy","night","zzz"],char:"😴",fitzpatrick_scale:false,category:"people"},zzz:{keywords:["sleepy","tired","dream"],char:"💤",fitzpatrick_scale:false,category:"people"},poop:{keywords:["hankey","shitface","fail","turd","shit"],char:"💩",fitzpatrick_scale:false,category:"people"},smiling_imp:{keywords:["devil","horns"],char:"😈",fitzpatrick_scale:false,category:"people"},imp:{keywords:["devil","angry","horns"],char:"👿",fitzpatrick_scale:false,category:"people"},japanese_ogre:{keywords:["monster","red","mask","halloween","scary","creepy","devil","demon","japanese","ogre"],char:"👹",fitzpatrick_scale:false,category:"people"},japanese_goblin:{keywords:["red","evil","mask","monster","scary","creepy","japanese","goblin"],char:"👺",fitzpatrick_scale:false,category:"people"},skull:{keywords:["dead","skeleton","creepy","death"],char:"💀",fitzpatrick_scale:false,category:"people"},ghost:{keywords:["halloween","spooky","scary"],char:"👻",fitzpatrick_scale:false,category:"people"},alien:{keywords:["UFO","paul","weird","outer_space"],char:"👽",fitzpatrick_scale:false,category:"people"},robot:{keywords:["computer","machine","bot"],char:"🤖",fitzpatrick_scale:false,category:"people"},smiley_cat:{keywords:["animal","cats","happy","smile"],char:"😺",fitzpatrick_scale:false,category:"people"},smile_cat:{keywords:["animal","cats","smile"],char:"😸",fitzpatrick_scale:false,category:"people"},joy_cat:{keywords:["animal","cats","haha","happy","tears"],char:"😹",fitzpatrick_scale:false,category:"people"},heart_eyes_cat:{keywords:["animal","love","like","affection","cats","valentines","heart"],char:"😻",fitzpatrick_scale:false,category:"people"},smirk_cat:{keywords:["animal","cats","smirk"],char:"😼",fitzpatrick_scale:false,category:"people"},kissing_cat:{keywords:["animal","cats","kiss"],char:"😽",fitzpatrick_scale:false,category:"people"},scream_cat:{keywords:["animal","cats","munch","scared","scream"],char:"🙀",fitzpatrick_scale:false,category:"people"},crying_cat_face:{keywords:["animal","tears","weep","sad","cats","upset","cry"],char:"😿",fitzpatrick_scale:false,category:"people"},pouting_cat:{keywords:["animal","cats"],char:"😾",fitzpatrick_scale:false,category:"people"},palms_up:{keywords:["hands","gesture","cupped","prayer"],char:"🤲",fitzpatrick_scale:true,category:"people"},raised_hands:{keywords:["gesture","hooray","yea","celebration","hands"],char:"🙌",fitzpatrick_scale:true,category:"people"},clap:{keywords:["hands","praise","applause","congrats","yay"],char:"👏",fitzpatrick_scale:true,category:"people"},wave:{keywords:["hands","gesture","goodbye","solong","farewell","hello","hi","palm"],char:"👋",fitzpatrick_scale:true,category:"people"},call_me_hand:{keywords:["hands","gesture"],char:"🤙",fitzpatrick_scale:true,category:"people"},"+1":{keywords:["thumbsup","yes","awesome","good","agree","accept","cool","hand","like"],char:"👍",fitzpatrick_scale:true,category:"people"},"-1":{keywords:["thumbsdown","no","dislike","hand"],char:"👎",fitzpatrick_scale:true,category:"people"},facepunch:{keywords:["angry","violence","fist","hit","attack","hand"],char:"👊",fitzpatrick_scale:true,category:"people"},fist:{keywords:["fingers","hand","grasp"],char:"✊",fitzpatrick_scale:true,category:"people"},fist_left:{keywords:["hand","fistbump"],char:"🤛",fitzpatrick_scale:true,category:"people"},fist_right:{keywords:["hand","fistbump"],char:"🤜",fitzpatrick_scale:true,category:"people"},v:{keywords:["fingers","ohyeah","hand","peace","victory","two"],char:"✌",fitzpatrick_scale:true,category:"people"},ok_hand:{keywords:["fingers","limbs","perfect","ok","okay"],char:"👌",fitzpatrick_scale:true,category:"people"},raised_hand:{keywords:["fingers","stop","highfive","palm","ban"],char:"✋",fitzpatrick_scale:true,category:"people"},raised_back_of_hand:{keywords:["fingers","raised","backhand"],char:"🤚",fitzpatrick_scale:true,category:"people"},open_hands:{keywords:["fingers","butterfly","hands","open"],char:"👐",fitzpatrick_scale:true,category:"people"},muscle:{keywords:["arm","flex","hand","summer","strong","biceps"],char:"💪",fitzpatrick_scale:true,category:"people"},pray:{keywords:["please","hope","wish","namaste","highfive"],char:"🙏",fitzpatrick_scale:true,category:"people"},foot:{keywords:["kick","stomp"],char:"🦶",fitzpatrick_scale:true,category:"people"},leg:{keywords:["kick","limb"],char:"🦵",fitzpatrick_scale:true,category:"people"},handshake:{keywords:["agreement","shake"],char:"🤝",fitzpatrick_scale:false,category:"people"},point_up:{keywords:["hand","fingers","direction","up"],char:"☝",fitzpatrick_scale:true,category:"people"},point_up_2:{keywords:["fingers","hand","direction","up"],char:"👆",fitzpatrick_scale:true,category:"people"},point_down:{keywords:["fingers","hand","direction","down"],char:"👇",fitzpatrick_scale:true,category:"people"},point_left:{keywords:["direction","fingers","hand","left"],char:"👈",fitzpatrick_scale:true,category:"people"},point_right:{keywords:["fingers","hand","direction","right"],char:"👉",fitzpatrick_scale:true,category:"people"},fu:{keywords:["hand","fingers","rude","middle","flipping"],char:"🖕",fitzpatrick_scale:true,category:"people"},raised_hand_with_fingers_splayed:{keywords:["hand","fingers","palm"],char:"🖐",fitzpatrick_scale:true,category:"people"},love_you:{keywords:["hand","fingers","gesture"],char:"🤟",fitzpatrick_scale:true,category:"people"},metal:{keywords:["hand","fingers","evil_eye","sign_of_horns","rock_on"],char:"🤘",fitzpatrick_scale:true,category:"people"},crossed_fingers:{keywords:["good","lucky"],char:"🤞",fitzpatrick_scale:true,category:"people"},vulcan_salute:{keywords:["hand","fingers","spock","star trek"],char:"🖖",fitzpatrick_scale:true,category:"people"},writing_hand:{keywords:["lower_left_ballpoint_pen","stationery","write","compose"],char:"✍",fitzpatrick_scale:true,category:"people"},selfie:{keywords:["camera","phone"],char:"🤳",fitzpatrick_scale:true,category:"people"},nail_care:{keywords:["beauty","manicure","finger","fashion","nail"],char:"💅",fitzpatrick_scale:true,category:"people"},lips:{keywords:["mouth","kiss"],char:"👄",fitzpatrick_scale:false,category:"people"},tooth:{keywords:["teeth","dentist"],char:"🦷",fitzpatrick_scale:false,category:"people"},tongue:{keywords:["mouth","playful"],char:"👅",fitzpatrick_scale:false,category:"people"},ear:{keywords:["face","hear","sound","listen"],char:"👂",fitzpatrick_scale:true,category:"people"},nose:{keywords:["smell","sniff"],char:"👃",fitzpatrick_scale:true,category:"people"},eye:{keywords:["face","look","see","watch","stare"],char:"👁",fitzpatrick_scale:false,category:"people"},eyes:{keywords:["look","watch","stalk","peek","see"],char:"👀",fitzpatrick_scale:false,category:"people"},brain:{keywords:["smart","intelligent"],char:"🧠",fitzpatrick_scale:false,category:"people"},bust_in_silhouette:{keywords:["user","person","human"],char:"👤",fitzpatrick_scale:false,category:"people"},busts_in_silhouette:{keywords:["user","person","human","group","team"],char:"👥",fitzpatrick_scale:false,category:"people"},speaking_head:{keywords:["user","person","human","sing","say","talk"],char:"🗣",fitzpatrick_scale:false,category:"people"},baby:{keywords:["child","boy","girl","toddler"],char:"👶",fitzpatrick_scale:true,category:"people"},child:{keywords:["gender-neutral","young"],char:"🧒",fitzpatrick_scale:true,category:"people"},boy:{keywords:["man","male","guy","teenager"],char:"👦",fitzpatrick_scale:true,category:"people"},girl:{keywords:["female","woman","teenager"],char:"👧",fitzpatrick_scale:true,category:"people"},adult:{keywords:["gender-neutral","person"],char:"🧑",fitzpatrick_scale:true,category:"people"},man:{keywords:["mustache","father","dad","guy","classy","sir","moustache"],char:"👨",fitzpatrick_scale:true,category:"people"},woman:{keywords:["female","girls","lady"],char:"👩",fitzpatrick_scale:true,category:"people"},blonde_woman:{keywords:["woman","female","girl","blonde","person"],char:"👱‍♀️",fitzpatrick_scale:true,category:"people"},blonde_man:{keywords:["man","male","boy","blonde","guy","person"],char:"👱",fitzpatrick_scale:true,category:"people"},bearded_person:{keywords:["person","bewhiskered"],char:"🧔",fitzpatrick_scale:true,category:"people"},older_adult:{keywords:["human","elder","senior","gender-neutral"],char:"🧓",fitzpatrick_scale:true,category:"people"},older_man:{keywords:["human","male","men","old","elder","senior"],char:"👴",fitzpatrick_scale:true,category:"people"},older_woman:{keywords:["human","female","women","lady","old","elder","senior"],char:"👵",fitzpatrick_scale:true,category:"people"},man_with_gua_pi_mao:{keywords:["male","boy","chinese"],char:"👲",fitzpatrick_scale:true,category:"people"},woman_with_headscarf:{keywords:["female","hijab","mantilla","tichel"],char:"🧕",fitzpatrick_scale:true,category:"people"},woman_with_turban:{keywords:["female","indian","hinduism","arabs","woman"],char:"👳‍♀️",fitzpatrick_scale:true,category:"people"},man_with_turban:{keywords:["male","indian","hinduism","arabs"],char:"👳",fitzpatrick_scale:true,category:"people"},policewoman:{keywords:["woman","police","law","legal","enforcement","arrest","911","female"],char:"👮‍♀️",fitzpatrick_scale:true,category:"people"},policeman:{keywords:["man","police","law","legal","enforcement","arrest","911"],char:"👮",fitzpatrick_scale:true,category:"people"},construction_worker_woman:{keywords:["female","human","wip","build","construction","worker","labor","woman"],char:"👷‍♀️",fitzpatrick_scale:true,category:"people"},construction_worker_man:{keywords:["male","human","wip","guy","build","construction","worker","labor"],char:"👷",fitzpatrick_scale:true,category:"people"},guardswoman:{keywords:["uk","gb","british","female","royal","woman"],char:"💂‍♀️",fitzpatrick_scale:true,category:"people"},guardsman:{keywords:["uk","gb","british","male","guy","royal"],char:"💂",fitzpatrick_scale:true,category:"people"},female_detective:{keywords:["human","spy","detective","female","woman"],char:"🕵️‍♀️",fitzpatrick_scale:true,category:"people"},male_detective:{keywords:["human","spy","detective"],char:"🕵",fitzpatrick_scale:true,category:"people"},woman_health_worker:{keywords:["doctor","nurse","therapist","healthcare","woman","human"],char:"👩‍⚕️",fitzpatrick_scale:true,category:"people"},man_health_worker:{keywords:["doctor","nurse","therapist","healthcare","man","human"],char:"👨‍⚕️",fitzpatrick_scale:true,category:"people"},woman_farmer:{keywords:["rancher","gardener","woman","human"],char:"👩‍🌾",fitzpatrick_scale:true,category:"people"},man_farmer:{keywords:["rancher","gardener","man","human"],char:"👨‍🌾",fitzpatrick_scale:true,category:"people"},woman_cook:{keywords:["chef","woman","human"],char:"👩‍🍳",fitzpatrick_scale:true,category:"people"},man_cook:{keywords:["chef","man","human"],char:"👨‍🍳",fitzpatrick_scale:true,category:"people"},woman_student:{keywords:["graduate","woman","human"],char:"👩‍🎓",fitzpatrick_scale:true,category:"people"},man_student:{keywords:["graduate","man","human"],char:"👨‍🎓",fitzpatrick_scale:true,category:"people"},woman_singer:{keywords:["rockstar","entertainer","woman","human"],char:"👩‍🎤",fitzpatrick_scale:true,category:"people"},man_singer:{keywords:["rockstar","entertainer","man","human"],char:"👨‍🎤",fitzpatrick_scale:true,category:"people"},woman_teacher:{keywords:["instructor","professor","woman","human"],char:"👩‍🏫",fitzpatrick_scale:true,category:"people"},man_teacher:{keywords:["instructor","professor","man","human"],char:"👨‍🏫",fitzpatrick_scale:true,category:"people"},woman_factory_worker:{keywords:["assembly","industrial","woman","human"],char:"👩‍🏭",fitzpatrick_scale:true,category:"people"},man_factory_worker:{keywords:["assembly","industrial","man","human"],char:"👨‍🏭",fitzpatrick_scale:true,category:"people"},woman_technologist:{keywords:["coder","developer","engineer","programmer","software","woman","human","laptop","computer"],char:"👩‍💻",fitzpatrick_scale:true,category:"people"},man_technologist:{keywords:["coder","developer","engineer","programmer","software","man","human","laptop","computer"],char:"👨‍💻",fitzpatrick_scale:true,category:"people"},woman_office_worker:{keywords:["business","manager","woman","human"],char:"👩‍💼",fitzpatrick_scale:true,category:"people"},man_office_worker:{keywords:["business","manager","man","human"],char:"👨‍💼",fitzpatrick_scale:true,category:"people"},woman_mechanic:{keywords:["plumber","woman","human","wrench"],char:"👩‍🔧",fitzpatrick_scale:true,category:"people"},man_mechanic:{keywords:["plumber","man","human","wrench"],char:"👨‍🔧",fitzpatrick_scale:true,category:"people"},woman_scientist:{keywords:["biologist","chemist","engineer","physicist","woman","human"],char:"👩‍🔬",fitzpatrick_scale:true,category:"people"},man_scientist:{keywords:["biologist","chemist","engineer","physicist","man","human"],char:"👨‍🔬",fitzpatrick_scale:true,category:"people"},woman_artist:{keywords:["painter","woman","human"],char:"👩‍🎨",fitzpatrick_scale:true,category:"people"},man_artist:{keywords:["painter","man","human"],char:"👨‍🎨",fitzpatrick_scale:true,category:"people"},woman_firefighter:{keywords:["fireman","woman","human"],char:"👩‍🚒",fitzpatrick_scale:true,category:"people"},man_firefighter:{keywords:["fireman","man","human"],char:"👨‍🚒",fitzpatrick_scale:true,category:"people"},woman_pilot:{keywords:["aviator","plane","woman","human"],char:"👩‍✈️",fitzpatrick_scale:true,category:"people"},man_pilot:{keywords:["aviator","plane","man","human"],char:"👨‍✈️",fitzpatrick_scale:true,category:"people"},woman_astronaut:{keywords:["space","rocket","woman","human"],char:"👩‍🚀",fitzpatrick_scale:true,category:"people"},man_astronaut:{keywords:["space","rocket","man","human"],char:"👨‍🚀",fitzpatrick_scale:true,category:"people"},woman_judge:{keywords:["justice","court","woman","human"],char:"👩‍⚖️",fitzpatrick_scale:true,category:"people"},man_judge:{keywords:["justice","court","man","human"],char:"👨‍⚖️",fitzpatrick_scale:true,category:"people"},woman_superhero:{keywords:["woman","female","good","heroine","superpowers"],char:"🦸‍♀️",fitzpatrick_scale:true,category:"people"},man_superhero:{keywords:["man","male","good","hero","superpowers"],char:"🦸‍♂️",fitzpatrick_scale:true,category:"people"},woman_supervillain:{keywords:["woman","female","evil","bad","criminal","heroine","superpowers"],char:"🦹‍♀️",fitzpatrick_scale:true,category:"people"},man_supervillain:{keywords:["man","male","evil","bad","criminal","hero","superpowers"],char:"🦹‍♂️",fitzpatrick_scale:true,category:"people"},mrs_claus:{keywords:["woman","female","xmas","mother christmas"],char:"🤶",fitzpatrick_scale:true,category:"people"},santa:{keywords:["festival","man","male","xmas","father christmas"],char:"🎅",fitzpatrick_scale:true,category:"people"},sorceress:{keywords:["woman","female","mage","witch"],char:"🧙‍♀️",fitzpatrick_scale:true,category:"people"},wizard:{keywords:["man","male","mage","sorcerer"],char:"🧙‍♂️",fitzpatrick_scale:true,category:"people"},woman_elf:{keywords:["woman","female"],char:"🧝‍♀️",fitzpatrick_scale:true,category:"people"},man_elf:{keywords:["man","male"],char:"🧝‍♂️",fitzpatrick_scale:true,category:"people"},woman_vampire:{keywords:["woman","female"],char:"🧛‍♀️",fitzpatrick_scale:true,category:"people"},man_vampire:{keywords:["man","male","dracula"],char:"🧛‍♂️",fitzpatrick_scale:true,category:"people"},woman_zombie:{keywords:["woman","female","undead","walking dead"],char:"🧟‍♀️",fitzpatrick_scale:false,category:"people"},man_zombie:{keywords:["man","male","dracula","undead","walking dead"],char:"🧟‍♂️",fitzpatrick_scale:false,category:"people"},woman_genie:{keywords:["woman","female"],char:"🧞‍♀️",fitzpatrick_scale:false,category:"people"},man_genie:{keywords:["man","male"],char:"🧞‍♂️",fitzpatrick_scale:false,category:"people"},mermaid:{keywords:["woman","female","merwoman","ariel"],char:"🧜‍♀️",fitzpatrick_scale:true,category:"people"},merman:{keywords:["man","male","triton"],char:"🧜‍♂️",fitzpatrick_scale:true,category:"people"},woman_fairy:{keywords:["woman","female"],char:"🧚‍♀️",fitzpatrick_scale:true,category:"people"},man_fairy:{keywords:["man","male"],char:"🧚‍♂️",fitzpatrick_scale:true,category:"people"},angel:{keywords:["heaven","wings","halo"],char:"👼",fitzpatrick_scale:true,category:"people"},pregnant_woman:{keywords:["baby"],char:"🤰",fitzpatrick_scale:true,category:"people"},breastfeeding:{keywords:["nursing","baby"],char:"🤱",fitzpatrick_scale:true,category:"people"},princess:{keywords:["girl","woman","female","blond","crown","royal","queen"],char:"👸",fitzpatrick_scale:true,category:"people"},prince:{keywords:["boy","man","male","crown","royal","king"],char:"🤴",fitzpatrick_scale:true,category:"people"},bride_with_veil:{keywords:["couple","marriage","wedding","woman","bride"],char:"👰",fitzpatrick_scale:true,category:"people"},man_in_tuxedo:{keywords:["couple","marriage","wedding","groom"],char:"🤵",fitzpatrick_scale:true,category:"people"},running_woman:{keywords:["woman","walking","exercise","race","running","female"],char:"🏃‍♀️",fitzpatrick_scale:true,category:"people"},running_man:{keywords:["man","walking","exercise","race","running"],char:"🏃",fitzpatrick_scale:true,category:"people"},walking_woman:{keywords:["human","feet","steps","woman","female"],char:"🚶‍♀️",fitzpatrick_scale:true,category:"people"},walking_man:{keywords:["human","feet","steps"],char:"🚶",fitzpatrick_scale:true,category:"people"},dancer:{keywords:["female","girl","woman","fun"],char:"💃",fitzpatrick_scale:true,category:"people"},man_dancing:{keywords:["male","boy","fun","dancer"],char:"🕺",fitzpatrick_scale:true,category:"people"},dancing_women:{keywords:["female","bunny","women","girls"],char:"👯",fitzpatrick_scale:false,category:"people"},dancing_men:{keywords:["male","bunny","men","boys"],char:"👯‍♂️",fitzpatrick_scale:false,category:"people"},couple:{keywords:["pair","people","human","love","date","dating","like","affection","valentines","marriage"],char:"👫",fitzpatrick_scale:false,category:"people"},two_men_holding_hands:{keywords:["pair","couple","love","like","bromance","friendship","people","human"],char:"👬",fitzpatrick_scale:false,category:"people"},two_women_holding_hands:{keywords:["pair","friendship","couple","love","like","female","people","human"],char:"👭",fitzpatrick_scale:false,category:"people"},bowing_woman:{keywords:["woman","female","girl"],char:"🙇‍♀️",fitzpatrick_scale:true,category:"people"},bowing_man:{keywords:["man","male","boy"],char:"🙇",fitzpatrick_scale:true,category:"people"},man_facepalming:{keywords:["man","male","boy","disbelief"],char:"🤦‍♂️",fitzpatrick_scale:true,category:"people"},woman_facepalming:{keywords:["woman","female","girl","disbelief"],char:"🤦‍♀️",fitzpatrick_scale:true,category:"people"},woman_shrugging:{keywords:["woman","female","girl","confused","indifferent","doubt"],char:"🤷",fitzpatrick_scale:true,category:"people"},man_shrugging:{keywords:["man","male","boy","confused","indifferent","doubt"],char:"🤷‍♂️",fitzpatrick_scale:true,category:"people"},tipping_hand_woman:{keywords:["female","girl","woman","human","information"],char:"💁",fitzpatrick_scale:true,category:"people"},tipping_hand_man:{keywords:["male","boy","man","human","information"],char:"💁‍♂️",fitzpatrick_scale:true,category:"people"},no_good_woman:{keywords:["female","girl","woman","nope"],char:"🙅",fitzpatrick_scale:true,category:"people"},no_good_man:{keywords:["male","boy","man","nope"],char:"🙅‍♂️",fitzpatrick_scale:true,category:"people"},ok_woman:{keywords:["women","girl","female","pink","human","woman"],char:"🙆",fitzpatrick_scale:true,category:"people"},ok_man:{keywords:["men","boy","male","blue","human","man"],char:"🙆‍♂️",fitzpatrick_scale:true,category:"people"},raising_hand_woman:{keywords:["female","girl","woman"],char:"🙋",fitzpatrick_scale:true,category:"people"},raising_hand_man:{keywords:["male","boy","man"],char:"🙋‍♂️",fitzpatrick_scale:true,category:"people"},pouting_woman:{keywords:["female","girl","woman"],char:"🙎",fitzpatrick_scale:true,category:"people"},pouting_man:{keywords:["male","boy","man"],char:"🙎‍♂️",fitzpatrick_scale:true,category:"people"},frowning_woman:{keywords:["female","girl","woman","sad","depressed","discouraged","unhappy"],char:"🙍",fitzpatrick_scale:true,category:"people"},frowning_man:{keywords:["male","boy","man","sad","depressed","discouraged","unhappy"],char:"🙍‍♂️",fitzpatrick_scale:true,category:"people"},haircut_woman:{keywords:["female","girl","woman"],char:"💇",fitzpatrick_scale:true,category:"people"},haircut_man:{keywords:["male","boy","man"],char:"💇‍♂️",fitzpatrick_scale:true,category:"people"},massage_woman:{keywords:["female","girl","woman","head"],char:"💆",fitzpatrick_scale:true,category:"people"},massage_man:{keywords:["male","boy","man","head"],char:"💆‍♂️",fitzpatrick_scale:true,category:"people"},woman_in_steamy_room:{keywords:["female","woman","spa","steamroom","sauna"],char:"🧖‍♀️",fitzpatrick_scale:true,category:"people"},man_in_steamy_room:{keywords:["male","man","spa","steamroom","sauna"],char:"🧖‍♂️",fitzpatrick_scale:true,category:"people"},couple_with_heart_woman_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:"💑",fitzpatrick_scale:false,category:"people"},couple_with_heart_woman_woman:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:"👩‍❤️‍👩",fitzpatrick_scale:false,category:"people"},couple_with_heart_man_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:"👨‍❤️‍👨",fitzpatrick_scale:false,category:"people"},couplekiss_man_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:"💏",fitzpatrick_scale:false,category:"people"},couplekiss_woman_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:"👩‍❤️‍💋‍👩",fitzpatrick_scale:false,category:"people"},couplekiss_man_man:{keywords:["pair","valentines","love","like","dating","marriage"],char:"👨‍❤️‍💋‍👨",fitzpatrick_scale:false,category:"people"},family_man_woman_boy:{keywords:["home","parents","child","mom","dad","father","mother","people","human"],char:"👪",fitzpatrick_scale:false,category:"people"},family_man_woman_girl:{keywords:["home","parents","people","human","child"],char:"👨‍👩‍👧",fitzpatrick_scale:false,category:"people"},family_man_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:"👨‍👩‍👧‍👦",fitzpatrick_scale:false,category:"people"},family_man_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:"👨‍👩‍👦‍👦",fitzpatrick_scale:false,category:"people"},family_man_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:"👨‍👩‍👧‍👧",fitzpatrick_scale:false,category:"people"},family_woman_woman_boy:{keywords:["home","parents","people","human","children"],char:"👩‍👩‍👦",fitzpatrick_scale:false,category:"people"},family_woman_woman_girl:{keywords:["home","parents","people","human","children"],char:"👩‍👩‍👧",fitzpatrick_scale:false,category:"people"},family_woman_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:"👩‍👩‍👧‍👦",fitzpatrick_scale:false,category:"people"},family_woman_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:"👩‍👩‍👦‍👦",fitzpatrick_scale:false,category:"people"},family_woman_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:"👩‍👩‍👧‍👧",fitzpatrick_scale:false,category:"people"},family_man_man_boy:{keywords:["home","parents","people","human","children"],char:"👨‍👨‍👦",fitzpatrick_scale:false,category:"people"},family_man_man_girl:{keywords:["home","parents","people","human","children"],char:"👨‍👨‍👧",fitzpatrick_scale:false,category:"people"},family_man_man_girl_boy:{keywords:["home","parents","people","human","children"],char:"👨‍👨‍👧‍👦",fitzpatrick_scale:false,category:"people"},family_man_man_boy_boy:{keywords:["home","parents","people","human","children"],char:"👨‍👨‍👦‍👦",fitzpatrick_scale:false,category:"people"},family_man_man_girl_girl:{keywords:["home","parents","people","human","children"],char:"👨‍👨‍👧‍👧",fitzpatrick_scale:false,category:"people"},family_woman_boy:{keywords:["home","parent","people","human","child"],char:"👩‍👦",fitzpatrick_scale:false,category:"people"},family_woman_girl:{keywords:["home","parent","people","human","child"],char:"👩‍👧",fitzpatrick_scale:false,category:"people"},family_woman_girl_boy:{keywords:["home","parent","people","human","children"],char:"👩‍👧‍👦",fitzpatrick_scale:false,category:"people"},family_woman_boy_boy:{keywords:["home","parent","people","human","children"],char:"👩‍👦‍👦",fitzpatrick_scale:false,category:"people"},family_woman_girl_girl:{keywords:["home","parent","people","human","children"],char:"👩‍👧‍👧",fitzpatrick_scale:false,category:"people"},family_man_boy:{keywords:["home","parent","people","human","child"],char:"👨‍👦",fitzpatrick_scale:false,category:"people"},family_man_girl:{keywords:["home","parent","people","human","child"],char:"👨‍👧",fitzpatrick_scale:false,category:"people"},family_man_girl_boy:{keywords:["home","parent","people","human","children"],char:"👨‍👧‍👦",fitzpatrick_scale:false,category:"people"},family_man_boy_boy:{keywords:["home","parent","people","human","children"],char:"👨‍👦‍👦",fitzpatrick_scale:false,category:"people"},family_man_girl_girl:{keywords:["home","parent","people","human","children"],char:"👨‍👧‍👧",fitzpatrick_scale:false,category:"people"},yarn:{keywords:["ball","crochet","knit"],char:"🧶",fitzpatrick_scale:false,category:"people"},thread:{keywords:["needle","sewing","spool","string"],char:"🧵",fitzpatrick_scale:false,category:"people"},coat:{keywords:["jacket"],char:"🧥",fitzpatrick_scale:false,category:"people"},labcoat:{keywords:["doctor","experiment","scientist","chemist"],char:"🥼",fitzpatrick_scale:false,category:"people"},womans_clothes:{keywords:["fashion","shopping_bags","female"],char:"👚",fitzpatrick_scale:false,category:"people"},tshirt:{keywords:["fashion","cloth","casual","shirt","tee"],char:"👕",fitzpatrick_scale:false,category:"people"},jeans:{keywords:["fashion","shopping"],char:"👖",fitzpatrick_scale:false,category:"people"},necktie:{keywords:["shirt","suitup","formal","fashion","cloth","business"],char:"👔",fitzpatrick_scale:false,category:"people"},dress:{keywords:["clothes","fashion","shopping"],char:"👗",fitzpatrick_scale:false,category:"people"},bikini:{keywords:["swimming","female","woman","girl","fashion","beach","summer"],char:"👙",fitzpatrick_scale:false,category:"people"},kimono:{keywords:["dress","fashion","women","female","japanese"],char:"👘",fitzpatrick_scale:false,category:"people"},lipstick:{keywords:["female","girl","fashion","woman"],char:"💄",fitzpatrick_scale:false,category:"people"},kiss:{keywords:["face","lips","love","like","affection","valentines"],char:"💋",fitzpatrick_scale:false,category:"people"},footprints:{keywords:["feet","tracking","walking","beach"],char:"👣",fitzpatrick_scale:false,category:"people"},flat_shoe:{keywords:["ballet","slip-on","slipper"],char:"🥿",fitzpatrick_scale:false,category:"people"},high_heel:{keywords:["fashion","shoes","female","pumps","stiletto"],char:"👠",fitzpatrick_scale:false,category:"people"},sandal:{keywords:["shoes","fashion","flip flops"],char:"👡",fitzpatrick_scale:false,category:"people"},boot:{keywords:["shoes","fashion"],char:"👢",fitzpatrick_scale:false,category:"people"},mans_shoe:{keywords:["fashion","male"],char:"👞",fitzpatrick_scale:false,category:"people"},athletic_shoe:{keywords:["shoes","sports","sneakers"],char:"👟",fitzpatrick_scale:false,category:"people"},hiking_boot:{keywords:["backpacking","camping","hiking"],char:"🥾",fitzpatrick_scale:false,category:"people"},socks:{keywords:["stockings","clothes"],char:"🧦",fitzpatrick_scale:false,category:"people"},gloves:{keywords:["hands","winter","clothes"],char:"🧤",fitzpatrick_scale:false,category:"people"},scarf:{keywords:["neck","winter","clothes"],char:"🧣",fitzpatrick_scale:false,category:"people"},womans_hat:{keywords:["fashion","accessories","female","lady","spring"],char:"👒",fitzpatrick_scale:false,category:"people"},tophat:{keywords:["magic","gentleman","classy","circus"],char:"🎩",fitzpatrick_scale:false,category:"people"},billed_hat:{keywords:["cap","baseball"],char:"🧢",fitzpatrick_scale:false,category:"people"},rescue_worker_helmet:{keywords:["construction","build"],char:"⛑",fitzpatrick_scale:false,category:"people"},mortar_board:{keywords:["school","college","degree","university","graduation","cap","hat","legal","learn","education"],char:"🎓",fitzpatrick_scale:false,category:"people"},crown:{keywords:["king","kod","leader","royalty","lord"],char:"👑",fitzpatrick_scale:false,category:"people"},school_satchel:{keywords:["student","education","bag","backpack"],char:"🎒",fitzpatrick_scale:false,category:"people"},luggage:{keywords:["packing","travel"],char:"🧳",fitzpatrick_scale:false,category:"people"},pouch:{keywords:["bag","accessories","shopping"],char:"👝",fitzpatrick_scale:false,category:"people"},purse:{keywords:["fashion","accessories","money","sales","shopping"],char:"👛",fitzpatrick_scale:false,category:"people"},handbag:{keywords:["fashion","accessory","accessories","shopping"],char:"👜",fitzpatrick_scale:false,category:"people"},briefcase:{keywords:["business","documents","work","law","legal","job","career"],char:"💼",fitzpatrick_scale:false,category:"people"},eyeglasses:{keywords:["fashion","accessories","eyesight","nerdy","dork","geek"],char:"👓",fitzpatrick_scale:false,category:"people"},dark_sunglasses:{keywords:["face","cool","accessories"],char:"🕶",fitzpatrick_scale:false,category:"people"},goggles:{keywords:["eyes","protection","safety"],char:"🥽",fitzpatrick_scale:false,category:"people"},ring:{keywords:["wedding","propose","marriage","valentines","diamond","fashion","jewelry","gem","engagement"],char:"💍",fitzpatrick_scale:false,category:"people"},closed_umbrella:{keywords:["weather","rain","drizzle"],char:"🌂",fitzpatrick_scale:false,category:"people"},dog:{keywords:["animal","friend","nature","woof","puppy","pet","faithful"],char:"🐶",fitzpatrick_scale:false,category:"animals_and_nature"},cat:{keywords:["animal","meow","nature","pet","kitten"],char:"🐱",fitzpatrick_scale:false,category:"animals_and_nature"},mouse:{keywords:["animal","nature","cheese_wedge","rodent"],char:"🐭",fitzpatrick_scale:false,category:"animals_and_nature"},hamster:{keywords:["animal","nature"],char:"🐹",fitzpatrick_scale:false,category:"animals_and_nature"},rabbit:{keywords:["animal","nature","pet","spring","magic","bunny"],char:"🐰",fitzpatrick_scale:false,category:"animals_and_nature"},fox_face:{keywords:["animal","nature","face"],char:"🦊",fitzpatrick_scale:false,category:"animals_and_nature"},bear:{keywords:["animal","nature","wild"],char:"🐻",fitzpatrick_scale:false,category:"animals_and_nature"},panda_face:{keywords:["animal","nature","panda"],char:"🐼",fitzpatrick_scale:false,category:"animals_and_nature"},koala:{keywords:["animal","nature"],char:"🐨",fitzpatrick_scale:false,category:"animals_and_nature"},tiger:{keywords:["animal","cat","danger","wild","nature","roar"],char:"🐯",fitzpatrick_scale:false,category:"animals_and_nature"},lion:{keywords:["animal","nature"],char:"🦁",fitzpatrick_scale:false,category:"animals_and_nature"},cow:{keywords:["beef","ox","animal","nature","moo","milk"],char:"🐮",fitzpatrick_scale:false,category:"animals_and_nature"},pig:{keywords:["animal","oink","nature"],char:"🐷",fitzpatrick_scale:false,category:"animals_and_nature"},pig_nose:{keywords:["animal","oink"],char:"🐽",fitzpatrick_scale:false,category:"animals_and_nature"},frog:{keywords:["animal","nature","croak","toad"],char:"🐸",fitzpatrick_scale:false,category:"animals_and_nature"},squid:{keywords:["animal","nature","ocean","sea"],char:"🦑",fitzpatrick_scale:false,category:"animals_and_nature"},octopus:{keywords:["animal","creature","ocean","sea","nature","beach"],char:"🐙",fitzpatrick_scale:false,category:"animals_and_nature"},shrimp:{keywords:["animal","ocean","nature","seafood"],char:"🦐",fitzpatrick_scale:false,category:"animals_and_nature"},monkey_face:{keywords:["animal","nature","circus"],char:"🐵",fitzpatrick_scale:false,category:"animals_and_nature"},gorilla:{keywords:["animal","nature","circus"],char:"🦍",fitzpatrick_scale:false,category:"animals_and_nature"},see_no_evil:{keywords:["monkey","animal","nature","haha"],char:"🙈",fitzpatrick_scale:false,category:"animals_and_nature"},hear_no_evil:{keywords:["animal","monkey","nature"],char:"🙉",fitzpatrick_scale:false,category:"animals_and_nature"},speak_no_evil:{keywords:["monkey","animal","nature","omg"],char:"🙊",fitzpatrick_scale:false,category:"animals_and_nature"},monkey:{keywords:["animal","nature","banana","circus"],char:"🐒",fitzpatrick_scale:false,category:"animals_and_nature"},chicken:{keywords:["animal","cluck","nature","bird"],char:"🐔",fitzpatrick_scale:false,category:"animals_and_nature"},penguin:{keywords:["animal","nature"],char:"🐧",fitzpatrick_scale:false,category:"animals_and_nature"},bird:{keywords:["animal","nature","fly","tweet","spring"],char:"🐦",fitzpatrick_scale:false,category:"animals_and_nature"},baby_chick:{keywords:["animal","chicken","bird"],char:"🐤",fitzpatrick_scale:false,category:"animals_and_nature"},hatching_chick:{keywords:["animal","chicken","egg","born","baby","bird"],char:"🐣",fitzpatrick_scale:false,category:"animals_and_nature"},hatched_chick:{keywords:["animal","chicken","baby","bird"],char:"🐥",fitzpatrick_scale:false,category:"animals_and_nature"},duck:{keywords:["animal","nature","bird","mallard"],char:"🦆",fitzpatrick_scale:false,category:"animals_and_nature"},eagle:{keywords:["animal","nature","bird"],char:"🦅",fitzpatrick_scale:false,category:"animals_and_nature"},owl:{keywords:["animal","nature","bird","hoot"],char:"🦉",fitzpatrick_scale:false,category:"animals_and_nature"},bat:{keywords:["animal","nature","blind","vampire"],char:"🦇",fitzpatrick_scale:false,category:"animals_and_nature"},wolf:{keywords:["animal","nature","wild"],char:"🐺",fitzpatrick_scale:false,category:"animals_and_nature"},boar:{keywords:["animal","nature"],char:"🐗",fitzpatrick_scale:false,category:"animals_and_nature"},horse:{keywords:["animal","brown","nature"],char:"🐴",fitzpatrick_scale:false,category:"animals_and_nature"},unicorn:{keywords:["animal","nature","mystical"],char:"🦄",fitzpatrick_scale:false,category:"animals_and_nature"},honeybee:{keywords:["animal","insect","nature","bug","spring","honey"],char:"🐝",fitzpatrick_scale:false,category:"animals_and_nature"},bug:{keywords:["animal","insect","nature","worm"],char:"🐛",fitzpatrick_scale:false,category:"animals_and_nature"},butterfly:{keywords:["animal","insect","nature","caterpillar"],char:"🦋",fitzpatrick_scale:false,category:"animals_and_nature"},snail:{keywords:["slow","animal","shell"],char:"🐌",fitzpatrick_scale:false,category:"animals_and_nature"},beetle:{keywords:["animal","insect","nature","ladybug"],char:"🐞",fitzpatrick_scale:false,category:"animals_and_nature"},ant:{keywords:["animal","insect","nature","bug"],char:"🐜",fitzpatrick_scale:false,category:"animals_and_nature"},grasshopper:{keywords:["animal","cricket","chirp"],char:"🦗",fitzpatrick_scale:false,category:"animals_and_nature"},spider:{keywords:["animal","arachnid"],char:"🕷",fitzpatrick_scale:false,category:"animals_and_nature"},scorpion:{keywords:["animal","arachnid"],char:"🦂",fitzpatrick_scale:false,category:"animals_and_nature"},crab:{keywords:["animal","crustacean"],char:"🦀",fitzpatrick_scale:false,category:"animals_and_nature"},snake:{keywords:["animal","evil","nature","hiss","python"],char:"🐍",fitzpatrick_scale:false,category:"animals_and_nature"},lizard:{keywords:["animal","nature","reptile"],char:"🦎",fitzpatrick_scale:false,category:"animals_and_nature"},"t-rex":{keywords:["animal","nature","dinosaur","tyrannosaurus","extinct"],char:"🦖",fitzpatrick_scale:false,category:"animals_and_nature"},sauropod:{keywords:["animal","nature","dinosaur","brachiosaurus","brontosaurus","diplodocus","extinct"],char:"🦕",fitzpatrick_scale:false,category:"animals_and_nature"},turtle:{keywords:["animal","slow","nature","tortoise"],char:"🐢",fitzpatrick_scale:false,category:"animals_and_nature"},tropical_fish:{keywords:["animal","swim","ocean","beach","nemo"],char:"🐠",fitzpatrick_scale:false,category:"animals_and_nature"},fish:{keywords:["animal","food","nature"],char:"🐟",fitzpatrick_scale:false,category:"animals_and_nature"},blowfish:{keywords:["animal","nature","food","sea","ocean"],char:"🐡",fitzpatrick_scale:false,category:"animals_and_nature"},dolphin:{keywords:["animal","nature","fish","sea","ocean","flipper","fins","beach"],char:"🐬",fitzpatrick_scale:false,category:"animals_and_nature"},shark:{keywords:["animal","nature","fish","sea","ocean","jaws","fins","beach"],char:"🦈",fitzpatrick_scale:false,category:"animals_and_nature"},whale:{keywords:["animal","nature","sea","ocean"],char:"🐳",fitzpatrick_scale:false,category:"animals_and_nature"},whale2:{keywords:["animal","nature","sea","ocean"],char:"🐋",fitzpatrick_scale:false,category:"animals_and_nature"},crocodile:{keywords:["animal","nature","reptile","lizard","alligator"],char:"🐊",fitzpatrick_scale:false,category:"animals_and_nature"},leopard:{keywords:["animal","nature"],char:"🐆",fitzpatrick_scale:false,category:"animals_and_nature"},zebra:{keywords:["animal","nature","stripes","safari"],char:"🦓",fitzpatrick_scale:false,category:"animals_and_nature"},tiger2:{keywords:["animal","nature","roar"],char:"🐅",fitzpatrick_scale:false,category:"animals_and_nature"},water_buffalo:{keywords:["animal","nature","ox","cow"],char:"🐃",fitzpatrick_scale:false,category:"animals_and_nature"},ox:{keywords:["animal","cow","beef"],char:"🐂",fitzpatrick_scale:false,category:"animals_and_nature"},cow2:{keywords:["beef","ox","animal","nature","moo","milk"],char:"🐄",fitzpatrick_scale:false,category:"animals_and_nature"},deer:{keywords:["animal","nature","horns","venison"],char:"🦌",fitzpatrick_scale:false,category:"animals_and_nature"},dromedary_camel:{keywords:["animal","hot","desert","hump"],char:"🐪",fitzpatrick_scale:false,category:"animals_and_nature"},camel:{keywords:["animal","nature","hot","desert","hump"],char:"🐫",fitzpatrick_scale:false,category:"animals_and_nature"},giraffe:{keywords:["animal","nature","spots","safari"],char:"🦒",fitzpatrick_scale:false,category:"animals_and_nature"},elephant:{keywords:["animal","nature","nose","th","circus"],char:"🐘",fitzpatrick_scale:false,category:"animals_and_nature"},rhinoceros:{keywords:["animal","nature","horn"],char:"🦏",fitzpatrick_scale:false,category:"animals_and_nature"},goat:{keywords:["animal","nature"],char:"🐐",fitzpatrick_scale:false,category:"animals_and_nature"},ram:{keywords:["animal","sheep","nature"],char:"🐏",fitzpatrick_scale:false,category:"animals_and_nature"},sheep:{keywords:["animal","nature","wool","shipit"],char:"🐑",fitzpatrick_scale:false,category:"animals_and_nature"},racehorse:{keywords:["animal","gamble","luck"],char:"🐎",fitzpatrick_scale:false,category:"animals_and_nature"},pig2:{keywords:["animal","nature"],char:"🐖",fitzpatrick_scale:false,category:"animals_and_nature"},rat:{keywords:["animal","mouse","rodent"],char:"🐀",fitzpatrick_scale:false,category:"animals_and_nature"},mouse2:{keywords:["animal","nature","rodent"],char:"🐁",fitzpatrick_scale:false,category:"animals_and_nature"},rooster:{keywords:["animal","nature","chicken"],char:"🐓",fitzpatrick_scale:false,category:"animals_and_nature"},turkey:{keywords:["animal","bird"],char:"🦃",fitzpatrick_scale:false,category:"animals_and_nature"},dove:{keywords:["animal","bird"],char:"🕊",fitzpatrick_scale:false,category:"animals_and_nature"},dog2:{keywords:["animal","nature","friend","doge","pet","faithful"],char:"🐕",fitzpatrick_scale:false,category:"animals_and_nature"},poodle:{keywords:["dog","animal","101","nature","pet"],char:"🐩",fitzpatrick_scale:false,category:"animals_and_nature"},cat2:{keywords:["animal","meow","pet","cats"],char:"🐈",fitzpatrick_scale:false,category:"animals_and_nature"},rabbit2:{keywords:["animal","nature","pet","magic","spring"],char:"🐇",fitzpatrick_scale:false,category:"animals_and_nature"},chipmunk:{keywords:["animal","nature","rodent","squirrel"],char:"🐿",fitzpatrick_scale:false,category:"animals_and_nature"},hedgehog:{keywords:["animal","nature","spiny"],char:"🦔",fitzpatrick_scale:false,category:"animals_and_nature"},raccoon:{keywords:["animal","nature"],char:"🦝",fitzpatrick_scale:false,category:"animals_and_nature"},llama:{keywords:["animal","nature","alpaca"],char:"🦙",fitzpatrick_scale:false,category:"animals_and_nature"},hippopotamus:{keywords:["animal","nature"],char:"🦛",fitzpatrick_scale:false,category:"animals_and_nature"},kangaroo:{keywords:["animal","nature","australia","joey","hop","marsupial"],char:"🦘",fitzpatrick_scale:false,category:"animals_and_nature"},badger:{keywords:["animal","nature","honey"],char:"🦡",fitzpatrick_scale:false,category:"animals_and_nature"},swan:{keywords:["animal","nature","bird"],char:"🦢",fitzpatrick_scale:false,category:"animals_and_nature"},peacock:{keywords:["animal","nature","peahen","bird"],char:"🦚",fitzpatrick_scale:false,category:"animals_and_nature"},parrot:{keywords:["animal","nature","bird","pirate","talk"],char:"🦜",fitzpatrick_scale:false,category:"animals_and_nature"},lobster:{keywords:["animal","nature","bisque","claws","seafood"],char:"🦞",fitzpatrick_scale:false,category:"animals_and_nature"},mosquito:{keywords:["animal","nature","insect","malaria"],char:"🦟",fitzpatrick_scale:false,category:"animals_and_nature"},paw_prints:{keywords:["animal","tracking","footprints","dog","cat","pet","feet"],char:"🐾",fitzpatrick_scale:false,category:"animals_and_nature"},dragon:{keywords:["animal","myth","nature","chinese","green"],char:"🐉",fitzpatrick_scale:false,category:"animals_and_nature"},dragon_face:{keywords:["animal","myth","nature","chinese","green"],char:"🐲",fitzpatrick_scale:false,category:"animals_and_nature"},cactus:{keywords:["vegetable","plant","nature"],char:"🌵",fitzpatrick_scale:false,category:"animals_and_nature"},christmas_tree:{keywords:["festival","vacation","december","xmas","celebration"],char:"🎄",fitzpatrick_scale:false,category:"animals_and_nature"},evergreen_tree:{keywords:["plant","nature"],char:"🌲",fitzpatrick_scale:false,category:"animals_and_nature"},deciduous_tree:{keywords:["plant","nature"],char:"🌳",fitzpatrick_scale:false,category:"animals_and_nature"},palm_tree:{keywords:["plant","vegetable","nature","summer","beach","mojito","tropical"],char:"🌴",fitzpatrick_scale:false,category:"animals_and_nature"},seedling:{keywords:["plant","nature","grass","lawn","spring"],char:"🌱",fitzpatrick_scale:false,category:"animals_and_nature"},herb:{keywords:["vegetable","plant","medicine","weed","grass","lawn"],char:"🌿",fitzpatrick_scale:false,category:"animals_and_nature"},shamrock:{keywords:["vegetable","plant","nature","irish","clover"],char:"☘",fitzpatrick_scale:false,category:"animals_and_nature"},four_leaf_clover:{keywords:["vegetable","plant","nature","lucky","irish"],char:"🍀",fitzpatrick_scale:false,category:"animals_and_nature"},bamboo:{keywords:["plant","nature","vegetable","panda","pine_decoration"],char:"🎍",fitzpatrick_scale:false,category:"animals_and_nature"},tanabata_tree:{keywords:["plant","nature","branch","summer"],char:"🎋",fitzpatrick_scale:false,category:"animals_and_nature"},leaves:{keywords:["nature","plant","tree","vegetable","grass","lawn","spring"],char:"🍃",fitzpatrick_scale:false,category:"animals_and_nature"},fallen_leaf:{keywords:["nature","plant","vegetable","leaves"],char:"🍂",fitzpatrick_scale:false,category:"animals_and_nature"},maple_leaf:{keywords:["nature","plant","vegetable","ca","fall"],char:"🍁",fitzpatrick_scale:false,category:"animals_and_nature"},ear_of_rice:{keywords:["nature","plant"],char:"🌾",fitzpatrick_scale:false,category:"animals_and_nature"},hibiscus:{keywords:["plant","vegetable","flowers","beach"],char:"🌺",fitzpatrick_scale:false,category:"animals_and_nature"},sunflower:{keywords:["nature","plant","fall"],char:"🌻",fitzpatrick_scale:false,category:"animals_and_nature"},rose:{keywords:["flowers","valentines","love","spring"],char:"🌹",fitzpatrick_scale:false,category:"animals_and_nature"},wilted_flower:{keywords:["plant","nature","flower"],char:"🥀",fitzpatrick_scale:false,category:"animals_and_nature"},tulip:{keywords:["flowers","plant","nature","summer","spring"],char:"🌷",fitzpatrick_scale:false,category:"animals_and_nature"},blossom:{keywords:["nature","flowers","yellow"],char:"🌼",fitzpatrick_scale:false,category:"animals_and_nature"},cherry_blossom:{keywords:["nature","plant","spring","flower"],char:"🌸",fitzpatrick_scale:false,category:"animals_and_nature"},bouquet:{keywords:["flowers","nature","spring"],char:"💐",fitzpatrick_scale:false,category:"animals_and_nature"},mushroom:{keywords:["plant","vegetable"],char:"🍄",fitzpatrick_scale:false,category:"animals_and_nature"},chestnut:{keywords:["food","squirrel"],char:"🌰",fitzpatrick_scale:false,category:"animals_and_nature"},jack_o_lantern:{keywords:["halloween","light","pumpkin","creepy","fall"],char:"🎃",fitzpatrick_scale:false,category:"animals_and_nature"},shell:{keywords:["nature","sea","beach"],char:"🐚",fitzpatrick_scale:false,category:"animals_and_nature"},spider_web:{keywords:["animal","insect","arachnid","silk"],char:"🕸",fitzpatrick_scale:false,category:"animals_and_nature"},earth_americas:{keywords:["globe","world","USA","international"],char:"🌎",fitzpatrick_scale:false,category:"animals_and_nature"},earth_africa:{keywords:["globe","world","international"],char:"🌍",fitzpatrick_scale:false,category:"animals_and_nature"},earth_asia:{keywords:["globe","world","east","international"],char:"🌏",fitzpatrick_scale:false,category:"animals_and_nature"},full_moon:{keywords:["nature","yellow","twilight","planet","space","night","evening","sleep"],char:"🌕",fitzpatrick_scale:false,category:"animals_and_nature"},waning_gibbous_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep","waxing_gibbous_moon"],char:"🌖",fitzpatrick_scale:false,category:"animals_and_nature"},last_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌗",fitzpatrick_scale:false,category:"animals_and_nature"},waning_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌘",fitzpatrick_scale:false,category:"animals_and_nature"},new_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌑",fitzpatrick_scale:false,category:"animals_and_nature"},waxing_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌒",fitzpatrick_scale:false,category:"animals_and_nature"},first_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌓",fitzpatrick_scale:false,category:"animals_and_nature"},waxing_gibbous_moon:{keywords:["nature","night","sky","gray","twilight","planet","space","evening","sleep"],char:"🌔",fitzpatrick_scale:false,category:"animals_and_nature"},new_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌚",fitzpatrick_scale:false,category:"animals_and_nature"},full_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌝",fitzpatrick_scale:false,category:"animals_and_nature"},first_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌛",fitzpatrick_scale:false,category:"animals_and_nature"},last_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"🌜",fitzpatrick_scale:false,category:"animals_and_nature"},sun_with_face:{keywords:["nature","morning","sky"],char:"🌞",fitzpatrick_scale:false,category:"animals_and_nature"},crescent_moon:{keywords:["night","sleep","sky","evening","magic"],char:"🌙",fitzpatrick_scale:false,category:"animals_and_nature"},star:{keywords:["night","yellow"],char:"⭐",fitzpatrick_scale:false,category:"animals_and_nature"},star2:{keywords:["night","sparkle","awesome","good","magic"],char:"🌟",fitzpatrick_scale:false,category:"animals_and_nature"},dizzy:{keywords:["star","sparkle","shoot","magic"],char:"💫",fitzpatrick_scale:false,category:"animals_and_nature"},sparkles:{keywords:["stars","shine","shiny","cool","awesome","good","magic"],char:"✨",fitzpatrick_scale:false,category:"animals_and_nature"},comet:{keywords:["space"],char:"☄",fitzpatrick_scale:false,category:"animals_and_nature"},sunny:{keywords:["weather","nature","brightness","summer","beach","spring"],char:"☀️",fitzpatrick_scale:false,category:"animals_and_nature"},sun_behind_small_cloud:{keywords:["weather"],char:"🌤",fitzpatrick_scale:false,category:"animals_and_nature"},partly_sunny:{keywords:["weather","nature","cloudy","morning","fall","spring"],char:"⛅",fitzpatrick_scale:false,category:"animals_and_nature"},sun_behind_large_cloud:{keywords:["weather"],char:"🌥",fitzpatrick_scale:false,category:"animals_and_nature"},sun_behind_rain_cloud:{keywords:["weather"],char:"🌦",fitzpatrick_scale:false,category:"animals_and_nature"},cloud:{keywords:["weather","sky"],char:"☁️",fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_rain:{keywords:["weather"],char:"🌧",fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_lightning_and_rain:{keywords:["weather","lightning"],char:"⛈",fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_lightning:{keywords:["weather","thunder"],char:"🌩",fitzpatrick_scale:false,category:"animals_and_nature"},zap:{keywords:["thunder","weather","lightning bolt","fast"],char:"⚡",fitzpatrick_scale:false,category:"animals_and_nature"},fire:{keywords:["hot","cook","flame"],char:"🔥",fitzpatrick_scale:false,category:"animals_and_nature"},boom:{keywords:["bomb","explode","explosion","collision","blown"],char:"💥",fitzpatrick_scale:false,category:"animals_and_nature"},snowflake:{keywords:["winter","season","cold","weather","christmas","xmas"],char:"❄️",fitzpatrick_scale:false,category:"animals_and_nature"},cloud_with_snow:{keywords:["weather"],char:"🌨",fitzpatrick_scale:false,category:"animals_and_nature"},snowman:{keywords:["winter","season","cold","weather","christmas","xmas","frozen","without_snow"],char:"⛄",fitzpatrick_scale:false,category:"animals_and_nature"},snowman_with_snow:{keywords:["winter","season","cold","weather","christmas","xmas","frozen"],char:"☃",fitzpatrick_scale:false,category:"animals_and_nature"},wind_face:{keywords:["gust","air"],char:"🌬",fitzpatrick_scale:false,category:"animals_and_nature"},dash:{keywords:["wind","air","fast","shoo","fart","smoke","puff"],char:"💨",fitzpatrick_scale:false,category:"animals_and_nature"},tornado:{keywords:["weather","cyclone","twister"],char:"🌪",fitzpatrick_scale:false,category:"animals_and_nature"},fog:{keywords:["weather"],char:"🌫",fitzpatrick_scale:false,category:"animals_and_nature"},open_umbrella:{keywords:["weather","spring"],char:"☂",fitzpatrick_scale:false,category:"animals_and_nature"},umbrella:{keywords:["rainy","weather","spring"],char:"☔",fitzpatrick_scale:false,category:"animals_and_nature"},droplet:{keywords:["water","drip","faucet","spring"],char:"💧",fitzpatrick_scale:false,category:"animals_and_nature"},sweat_drops:{keywords:["water","drip","oops"],char:"💦",fitzpatrick_scale:false,category:"animals_and_nature"},ocean:{keywords:["sea","water","wave","nature","tsunami","disaster"],char:"🌊",fitzpatrick_scale:false,category:"animals_and_nature"},green_apple:{keywords:["fruit","nature"],char:"🍏",fitzpatrick_scale:false,category:"food_and_drink"},apple:{keywords:["fruit","mac","school"],char:"🍎",fitzpatrick_scale:false,category:"food_and_drink"},pear:{keywords:["fruit","nature","food"],char:"🍐",fitzpatrick_scale:false,category:"food_and_drink"},tangerine:{keywords:["food","fruit","nature","orange"],char:"🍊",fitzpatrick_scale:false,category:"food_and_drink"},lemon:{keywords:["fruit","nature"],char:"🍋",fitzpatrick_scale:false,category:"food_and_drink"},banana:{keywords:["fruit","food","monkey"],char:"🍌",fitzpatrick_scale:false,category:"food_and_drink"},watermelon:{keywords:["fruit","food","picnic","summer"],char:"🍉",fitzpatrick_scale:false,category:"food_and_drink"},grapes:{keywords:["fruit","food","wine"],char:"🍇",fitzpatrick_scale:false,category:"food_and_drink"},strawberry:{keywords:["fruit","food","nature"],char:"🍓",fitzpatrick_scale:false,category:"food_and_drink"},melon:{keywords:["fruit","nature","food"],char:"🍈",fitzpatrick_scale:false,category:"food_and_drink"},cherries:{keywords:["food","fruit"],char:"🍒",fitzpatrick_scale:false,category:"food_and_drink"},peach:{keywords:["fruit","nature","food"],char:"🍑",fitzpatrick_scale:false,category:"food_and_drink"},pineapple:{keywords:["fruit","nature","food"],char:"🍍",fitzpatrick_scale:false,category:"food_and_drink"},coconut:{keywords:["fruit","nature","food","palm"],char:"🥥",fitzpatrick_scale:false,category:"food_and_drink"},kiwi_fruit:{keywords:["fruit","food"],char:"🥝",fitzpatrick_scale:false,category:"food_and_drink"},mango:{keywords:["fruit","food","tropical"],char:"🥭",fitzpatrick_scale:false,category:"food_and_drink"},avocado:{keywords:["fruit","food"],char:"🥑",fitzpatrick_scale:false,category:"food_and_drink"},broccoli:{keywords:["fruit","food","vegetable"],char:"🥦",fitzpatrick_scale:false,category:"food_and_drink"},tomato:{keywords:["fruit","vegetable","nature","food"],char:"🍅",fitzpatrick_scale:false,category:"food_and_drink"},eggplant:{keywords:["vegetable","nature","food","aubergine"],char:"🍆",fitzpatrick_scale:false,category:"food_and_drink"},cucumber:{keywords:["fruit","food","pickle"],char:"🥒",fitzpatrick_scale:false,category:"food_and_drink"},carrot:{keywords:["vegetable","food","orange"],char:"🥕",fitzpatrick_scale:false,category:"food_and_drink"},hot_pepper:{keywords:["food","spicy","chilli","chili"],char:"🌶",fitzpatrick_scale:false,category:"food_and_drink"},potato:{keywords:["food","tuber","vegatable","starch"],char:"🥔",fitzpatrick_scale:false,category:"food_and_drink"},corn:{keywords:["food","vegetable","plant"],char:"🌽",fitzpatrick_scale:false,category:"food_and_drink"},leafy_greens:{keywords:["food","vegetable","plant","bok choy","cabbage","kale","lettuce"],char:"🥬",fitzpatrick_scale:false,category:"food_and_drink"},sweet_potato:{keywords:["food","nature"],char:"🍠",fitzpatrick_scale:false,category:"food_and_drink"},peanuts:{keywords:["food","nut"],char:"🥜",fitzpatrick_scale:false,category:"food_and_drink"},honey_pot:{keywords:["bees","sweet","kitchen"],char:"🍯",fitzpatrick_scale:false,category:"food_and_drink"},croissant:{keywords:["food","bread","french"],char:"🥐",fitzpatrick_scale:false,category:"food_and_drink"},bread:{keywords:["food","wheat","breakfast","toast"],char:"🍞",fitzpatrick_scale:false,category:"food_and_drink"},baguette_bread:{keywords:["food","bread","french"],char:"🥖",fitzpatrick_scale:false,category:"food_and_drink"},bagel:{keywords:["food","bread","bakery","schmear"],char:"🥯",fitzpatrick_scale:false,category:"food_and_drink"},pretzel:{keywords:["food","bread","twisted"],char:"🥨",fitzpatrick_scale:false,category:"food_and_drink"},cheese:{keywords:["food","chadder"],char:"🧀",fitzpatrick_scale:false,category:"food_and_drink"},egg:{keywords:["food","chicken","breakfast"],char:"🥚",fitzpatrick_scale:false,category:"food_and_drink"},bacon:{keywords:["food","breakfast","pork","pig","meat"],char:"🥓",fitzpatrick_scale:false,category:"food_and_drink"},steak:{keywords:["food","cow","meat","cut","chop","lambchop","porkchop"],char:"🥩",fitzpatrick_scale:false,category:"food_and_drink"},pancakes:{keywords:["food","breakfast","flapjacks","hotcakes"],char:"🥞",fitzpatrick_scale:false,category:"food_and_drink"},poultry_leg:{keywords:["food","meat","drumstick","bird","chicken","turkey"],char:"🍗",fitzpatrick_scale:false,category:"food_and_drink"},meat_on_bone:{keywords:["good","food","drumstick"],char:"🍖",fitzpatrick_scale:false,category:"food_and_drink"},bone:{keywords:["skeleton"],char:"🦴",fitzpatrick_scale:false,category:"food_and_drink"},fried_shrimp:{keywords:["food","animal","appetizer","summer"],char:"🍤",fitzpatrick_scale:false,category:"food_and_drink"},fried_egg:{keywords:["food","breakfast","kitchen","egg"],char:"🍳",fitzpatrick_scale:false,category:"food_and_drink"},hamburger:{keywords:["meat","fast food","beef","cheeseburger","mcdonalds","burger king"],char:"🍔",fitzpatrick_scale:false,category:"food_and_drink"},fries:{keywords:["chips","snack","fast food"],char:"🍟",fitzpatrick_scale:false,category:"food_and_drink"},stuffed_flatbread:{keywords:["food","flatbread","stuffed","gyro"],char:"🥙",fitzpatrick_scale:false,category:"food_and_drink"},hotdog:{keywords:["food","frankfurter"],char:"🌭",fitzpatrick_scale:false,category:"food_and_drink"},pizza:{keywords:["food","party"],char:"🍕",fitzpatrick_scale:false,category:"food_and_drink"},sandwich:{keywords:["food","lunch","bread"],char:"🥪",fitzpatrick_scale:false,category:"food_and_drink"},canned_food:{keywords:["food","soup"],char:"🥫",fitzpatrick_scale:false,category:"food_and_drink"},spaghetti:{keywords:["food","italian","noodle"],char:"🍝",fitzpatrick_scale:false,category:"food_and_drink"},taco:{keywords:["food","mexican"],char:"🌮",fitzpatrick_scale:false,category:"food_and_drink"},burrito:{keywords:["food","mexican"],char:"🌯",fitzpatrick_scale:false,category:"food_and_drink"},green_salad:{keywords:["food","healthy","lettuce"],char:"🥗",fitzpatrick_scale:false,category:"food_and_drink"},shallow_pan_of_food:{keywords:["food","cooking","casserole","paella"],char:"🥘",fitzpatrick_scale:false,category:"food_and_drink"},ramen:{keywords:["food","japanese","noodle","chopsticks"],char:"🍜",fitzpatrick_scale:false,category:"food_and_drink"},stew:{keywords:["food","meat","soup"],char:"🍲",fitzpatrick_scale:false,category:"food_and_drink"},fish_cake:{keywords:["food","japan","sea","beach","narutomaki","pink","swirl","kamaboko","surimi","ramen"],char:"🍥",fitzpatrick_scale:false,category:"food_and_drink"},fortune_cookie:{keywords:["food","prophecy"],char:"🥠",fitzpatrick_scale:false,category:"food_and_drink"},sushi:{keywords:["food","fish","japanese","rice"],char:"🍣",fitzpatrick_scale:false,category:"food_and_drink"},bento:{keywords:["food","japanese","box"],char:"🍱",fitzpatrick_scale:false,category:"food_and_drink"},curry:{keywords:["food","spicy","hot","indian"],char:"🍛",fitzpatrick_scale:false,category:"food_and_drink"},rice_ball:{keywords:["food","japanese"],char:"🍙",fitzpatrick_scale:false,category:"food_and_drink"},rice:{keywords:["food","china","asian"],char:"🍚",fitzpatrick_scale:false,category:"food_and_drink"},rice_cracker:{keywords:["food","japanese"],char:"🍘",fitzpatrick_scale:false,category:"food_and_drink"},oden:{keywords:["food","japanese"],char:"🍢",fitzpatrick_scale:false,category:"food_and_drink"},dango:{keywords:["food","dessert","sweet","japanese","barbecue","meat"],char:"🍡",fitzpatrick_scale:false,category:"food_and_drink"},shaved_ice:{keywords:["hot","dessert","summer"],char:"🍧",fitzpatrick_scale:false,category:"food_and_drink"},ice_cream:{keywords:["food","hot","dessert"],char:"🍨",fitzpatrick_scale:false,category:"food_and_drink"},icecream:{keywords:["food","hot","dessert","summer"],char:"🍦",fitzpatrick_scale:false,category:"food_and_drink"},pie:{keywords:["food","dessert","pastry"],char:"🥧",fitzpatrick_scale:false,category:"food_and_drink"},cake:{keywords:["food","dessert"],char:"🍰",fitzpatrick_scale:false,category:"food_and_drink"},cupcake:{keywords:["food","dessert","bakery","sweet"],char:"🧁",fitzpatrick_scale:false,category:"food_and_drink"},moon_cake:{keywords:["food","autumn"],char:"🥮",fitzpatrick_scale:false,category:"food_and_drink"},birthday:{keywords:["food","dessert","cake"],char:"🎂",fitzpatrick_scale:false,category:"food_and_drink"},custard:{keywords:["dessert","food"],char:"🍮",fitzpatrick_scale:false,category:"food_and_drink"},candy:{keywords:["snack","dessert","sweet","lolly"],char:"🍬",fitzpatrick_scale:false,category:"food_and_drink"},lollipop:{keywords:["food","snack","candy","sweet"],char:"🍭",fitzpatrick_scale:false,category:"food_and_drink"},chocolate_bar:{keywords:["food","snack","dessert","sweet"],char:"🍫",fitzpatrick_scale:false,category:"food_and_drink"},popcorn:{keywords:["food","movie theater","films","snack"],char:"🍿",fitzpatrick_scale:false,category:"food_and_drink"},dumpling:{keywords:["food","empanada","pierogi","potsticker"],char:"🥟",fitzpatrick_scale:false,category:"food_and_drink"},doughnut:{keywords:["food","dessert","snack","sweet","donut"],char:"🍩",fitzpatrick_scale:false,category:"food_and_drink"},cookie:{keywords:["food","snack","oreo","chocolate","sweet","dessert"],char:"🍪",fitzpatrick_scale:false,category:"food_and_drink"},milk_glass:{keywords:["beverage","drink","cow"],char:"🥛",fitzpatrick_scale:false,category:"food_and_drink"},beer:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:"🍺",fitzpatrick_scale:false,category:"food_and_drink"},beers:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:"🍻",fitzpatrick_scale:false,category:"food_and_drink"},clinking_glasses:{keywords:["beverage","drink","party","alcohol","celebrate","cheers","wine","champagne","toast"],char:"🥂",fitzpatrick_scale:false,category:"food_and_drink"},wine_glass:{keywords:["drink","beverage","drunk","alcohol","booze"],char:"🍷",fitzpatrick_scale:false,category:"food_and_drink"},tumbler_glass:{keywords:["drink","beverage","drunk","alcohol","liquor","booze","bourbon","scotch","whisky","glass","shot"],char:"🥃",fitzpatrick_scale:false,category:"food_and_drink"},cocktail:{keywords:["drink","drunk","alcohol","beverage","booze","mojito"],char:"🍸",fitzpatrick_scale:false,category:"food_and_drink"},tropical_drink:{keywords:["beverage","cocktail","summer","beach","alcohol","booze","mojito"],char:"🍹",fitzpatrick_scale:false,category:"food_and_drink"},champagne:{keywords:["drink","wine","bottle","celebration"],char:"🍾",fitzpatrick_scale:false,category:"food_and_drink"},sake:{keywords:["wine","drink","drunk","beverage","japanese","alcohol","booze"],char:"🍶",fitzpatrick_scale:false,category:"food_and_drink"},tea:{keywords:["drink","bowl","breakfast","green","british"],char:"🍵",fitzpatrick_scale:false,category:"food_and_drink"},cup_with_straw:{keywords:["drink","soda"],char:"🥤",fitzpatrick_scale:false,category:"food_and_drink"},coffee:{keywords:["beverage","caffeine","latte","espresso"],char:"☕",fitzpatrick_scale:false,category:"food_and_drink"},baby_bottle:{keywords:["food","container","milk"],char:"🍼",fitzpatrick_scale:false,category:"food_and_drink"},salt:{keywords:["condiment","shaker"],char:"🧂",fitzpatrick_scale:false,category:"food_and_drink"},spoon:{keywords:["cutlery","kitchen","tableware"],char:"🥄",fitzpatrick_scale:false,category:"food_and_drink"},fork_and_knife:{keywords:["cutlery","kitchen"],char:"🍴",fitzpatrick_scale:false,category:"food_and_drink"},plate_with_cutlery:{keywords:["food","eat","meal","lunch","dinner","restaurant"],char:"🍽",fitzpatrick_scale:false,category:"food_and_drink"},bowl_with_spoon:{keywords:["food","breakfast","cereal","oatmeal","porridge"],char:"🥣",fitzpatrick_scale:false,category:"food_and_drink"},takeout_box:{keywords:["food","leftovers"],char:"🥡",fitzpatrick_scale:false,category:"food_and_drink"},chopsticks:{keywords:["food"],char:"🥢",fitzpatrick_scale:false,category:"food_and_drink"},soccer:{keywords:["sports","football"],char:"⚽",fitzpatrick_scale:false,category:"activity"},basketball:{keywords:["sports","balls","NBA"],char:"🏀",fitzpatrick_scale:false,category:"activity"},football:{keywords:["sports","balls","NFL"],char:"🏈",fitzpatrick_scale:false,category:"activity"},baseball:{keywords:["sports","balls"],char:"⚾",fitzpatrick_scale:false,category:"activity"},softball:{keywords:["sports","balls"],char:"🥎",fitzpatrick_scale:false,category:"activity"},tennis:{keywords:["sports","balls","green"],char:"🎾",fitzpatrick_scale:false,category:"activity"},volleyball:{keywords:["sports","balls"],char:"🏐",fitzpatrick_scale:false,category:"activity"},rugby_football:{keywords:["sports","team"],char:"🏉",fitzpatrick_scale:false,category:"activity"},flying_disc:{keywords:["sports","frisbee","ultimate"],char:"🥏",fitzpatrick_scale:false,category:"activity"},"8ball":{keywords:["pool","hobby","game","luck","magic"],char:"🎱",fitzpatrick_scale:false,category:"activity"},golf:{keywords:["sports","business","flag","hole","summer"],char:"⛳",fitzpatrick_scale:false,category:"activity"},golfing_woman:{keywords:["sports","business","woman","female"],char:"🏌️‍♀️",fitzpatrick_scale:false,category:"activity"},golfing_man:{keywords:["sports","business"],char:"🏌",fitzpatrick_scale:true,category:"activity"},ping_pong:{keywords:["sports","pingpong"],char:"🏓",fitzpatrick_scale:false,category:"activity"},badminton:{keywords:["sports"],char:"🏸",fitzpatrick_scale:false,category:"activity"},goal_net:{keywords:["sports"],char:"🥅",fitzpatrick_scale:false,category:"activity"},ice_hockey:{keywords:["sports"],char:"🏒",fitzpatrick_scale:false,category:"activity"},field_hockey:{keywords:["sports"],char:"🏑",fitzpatrick_scale:false,category:"activity"},lacrosse:{keywords:["sports","ball","stick"],char:"🥍",fitzpatrick_scale:false,category:"activity"},cricket:{keywords:["sports"],char:"🏏",fitzpatrick_scale:false,category:"activity"},ski:{keywords:["sports","winter","cold","snow"],char:"🎿",fitzpatrick_scale:false,category:"activity"},skier:{keywords:["sports","winter","snow"],char:"⛷",fitzpatrick_scale:false,category:"activity"},snowboarder:{keywords:["sports","winter"],char:"🏂",fitzpatrick_scale:true,category:"activity"},person_fencing:{keywords:["sports","fencing","sword"],char:"🤺",fitzpatrick_scale:false,category:"activity"},women_wrestling:{keywords:["sports","wrestlers"],char:"🤼‍♀️",fitzpatrick_scale:false,category:"activity"},men_wrestling:{keywords:["sports","wrestlers"],char:"🤼‍♂️",fitzpatrick_scale:false,category:"activity"},woman_cartwheeling:{keywords:["gymnastics"],char:"🤸‍♀️",fitzpatrick_scale:true,category:"activity"},man_cartwheeling:{keywords:["gymnastics"],char:"🤸‍♂️",fitzpatrick_scale:true,category:"activity"},woman_playing_handball:{keywords:["sports"],char:"🤾‍♀️",fitzpatrick_scale:true,category:"activity"},man_playing_handball:{keywords:["sports"],char:"🤾‍♂️",fitzpatrick_scale:true,category:"activity"},ice_skate:{keywords:["sports"],char:"⛸",fitzpatrick_scale:false,category:"activity"},curling_stone:{keywords:["sports"],char:"🥌",fitzpatrick_scale:false,category:"activity"},skateboard:{keywords:["board"],char:"🛹",fitzpatrick_scale:false,category:"activity"},sled:{keywords:["sleigh","luge","toboggan"],char:"🛷",fitzpatrick_scale:false,category:"activity"},bow_and_arrow:{keywords:["sports"],char:"🏹",fitzpatrick_scale:false,category:"activity"},fishing_pole_and_fish:{keywords:["food","hobby","summer"],char:"🎣",fitzpatrick_scale:false,category:"activity"},boxing_glove:{keywords:["sports","fighting"],char:"🥊",fitzpatrick_scale:false,category:"activity"},martial_arts_uniform:{keywords:["judo","karate","taekwondo"],char:"🥋",fitzpatrick_scale:false,category:"activity"},rowing_woman:{keywords:["sports","hobby","water","ship","woman","female"],char:"🚣‍♀️",fitzpatrick_scale:true,category:"activity"},rowing_man:{keywords:["sports","hobby","water","ship"],char:"🚣",fitzpatrick_scale:true,category:"activity"},climbing_woman:{keywords:["sports","hobby","woman","female","rock"],char:"🧗‍♀️",fitzpatrick_scale:true,category:"activity"},climbing_man:{keywords:["sports","hobby","man","male","rock"],char:"🧗‍♂️",fitzpatrick_scale:true,category:"activity"},swimming_woman:{keywords:["sports","exercise","human","athlete","water","summer","woman","female"],char:"🏊‍♀️",fitzpatrick_scale:true,category:"activity"},swimming_man:{keywords:["sports","exercise","human","athlete","water","summer"],char:"🏊",fitzpatrick_scale:true,category:"activity"},woman_playing_water_polo:{keywords:["sports","pool"],char:"🤽‍♀️",fitzpatrick_scale:true,category:"activity"},man_playing_water_polo:{keywords:["sports","pool"],char:"🤽‍♂️",fitzpatrick_scale:true,category:"activity"},woman_in_lotus_position:{keywords:["woman","female","meditation","yoga","serenity","zen","mindfulness"],char:"🧘‍♀️",fitzpatrick_scale:true,category:"activity"},man_in_lotus_position:{keywords:["man","male","meditation","yoga","serenity","zen","mindfulness"],char:"🧘‍♂️",fitzpatrick_scale:true,category:"activity"},surfing_woman:{keywords:["sports","ocean","sea","summer","beach","woman","female"],char:"🏄‍♀️",fitzpatrick_scale:true,category:"activity"},surfing_man:{keywords:["sports","ocean","sea","summer","beach"],char:"🏄",fitzpatrick_scale:true,category:"activity"},bath:{keywords:["clean","shower","bathroom"],char:"🛀",fitzpatrick_scale:true,category:"activity"},basketball_woman:{keywords:["sports","human","woman","female"],char:"⛹️‍♀️",fitzpatrick_scale:true,category:"activity"},basketball_man:{keywords:["sports","human"],char:"⛹",fitzpatrick_scale:true,category:"activity"},weight_lifting_woman:{keywords:["sports","training","exercise","woman","female"],char:"🏋️‍♀️",fitzpatrick_scale:true,category:"activity"},weight_lifting_man:{keywords:["sports","training","exercise"],char:"🏋",fitzpatrick_scale:true,category:"activity"},biking_woman:{keywords:["sports","bike","exercise","hipster","woman","female"],char:"🚴‍♀️",fitzpatrick_scale:true,category:"activity"},biking_man:{keywords:["sports","bike","exercise","hipster"],char:"🚴",fitzpatrick_scale:true,category:"activity"},mountain_biking_woman:{keywords:["transportation","sports","human","race","bike","woman","female"],char:"🚵‍♀️",fitzpatrick_scale:true,category:"activity"},mountain_biking_man:{keywords:["transportation","sports","human","race","bike"],char:"🚵",fitzpatrick_scale:true,category:"activity"},horse_racing:{keywords:["animal","betting","competition","gambling","luck"],char:"🏇",fitzpatrick_scale:true,category:"activity"},business_suit_levitating:{keywords:["suit","business","levitate","hover","jump"],char:"🕴",fitzpatrick_scale:true,category:"activity"},trophy:{keywords:["win","award","contest","place","ftw","ceremony"],char:"🏆",fitzpatrick_scale:false,category:"activity"},running_shirt_with_sash:{keywords:["play","pageant"],char:"🎽",fitzpatrick_scale:false,category:"activity"},medal_sports:{keywords:["award","winning"],char:"🏅",fitzpatrick_scale:false,category:"activity"},medal_military:{keywords:["award","winning","army"],char:"🎖",fitzpatrick_scale:false,category:"activity"},"1st_place_medal":{keywords:["award","winning","first"],char:"🥇",fitzpatrick_scale:false,category:"activity"},"2nd_place_medal":{keywords:["award","second"],char:"🥈",fitzpatrick_scale:false,category:"activity"},"3rd_place_medal":{keywords:["award","third"],char:"🥉",fitzpatrick_scale:false,category:"activity"},reminder_ribbon:{keywords:["sports","cause","support","awareness"],char:"🎗",fitzpatrick_scale:false,category:"activity"},rosette:{keywords:["flower","decoration","military"],char:"🏵",fitzpatrick_scale:false,category:"activity"},ticket:{keywords:["event","concert","pass"],char:"🎫",fitzpatrick_scale:false,category:"activity"},tickets:{keywords:["sports","concert","entrance"],char:"🎟",fitzpatrick_scale:false,category:"activity"},performing_arts:{keywords:["acting","theater","drama"],char:"🎭",fitzpatrick_scale:false,category:"activity"},art:{keywords:["design","paint","draw","colors"],char:"🎨",fitzpatrick_scale:false,category:"activity"},circus_tent:{keywords:["festival","carnival","party"],char:"🎪",fitzpatrick_scale:false,category:"activity"},woman_juggling:{keywords:["juggle","balance","skill","multitask"],char:"🤹‍♀️",fitzpatrick_scale:true,category:"activity"},man_juggling:{keywords:["juggle","balance","skill","multitask"],char:"🤹‍♂️",fitzpatrick_scale:true,category:"activity"},microphone:{keywords:["sound","music","PA","sing","talkshow"],char:"🎤",fitzpatrick_scale:false,category:"activity"},headphones:{keywords:["music","score","gadgets"],char:"🎧",fitzpatrick_scale:false,category:"activity"},musical_score:{keywords:["treble","clef","compose"],char:"🎼",fitzpatrick_scale:false,category:"activity"},musical_keyboard:{keywords:["piano","instrument","compose"],char:"🎹",fitzpatrick_scale:false,category:"activity"},drum:{keywords:["music","instrument","drumsticks","snare"],char:"🥁",fitzpatrick_scale:false,category:"activity"},saxophone:{keywords:["music","instrument","jazz","blues"],char:"🎷",fitzpatrick_scale:false,category:"activity"},trumpet:{keywords:["music","brass"],char:"🎺",fitzpatrick_scale:false,category:"activity"},guitar:{keywords:["music","instrument"],char:"🎸",fitzpatrick_scale:false,category:"activity"},violin:{keywords:["music","instrument","orchestra","symphony"],char:"🎻",fitzpatrick_scale:false,category:"activity"},clapper:{keywords:["movie","film","record"],char:"🎬",fitzpatrick_scale:false,category:"activity"},video_game:{keywords:["play","console","PS4","controller"],char:"🎮",fitzpatrick_scale:false,category:"activity"},space_invader:{keywords:["game","arcade","play"],char:"👾",fitzpatrick_scale:false,category:"activity"},dart:{keywords:["game","play","bar","target","bullseye"],char:"🎯",fitzpatrick_scale:false,category:"activity"},game_die:{keywords:["dice","random","tabletop","play","luck"],char:"🎲",fitzpatrick_scale:false,category:"activity"},chess_pawn:{keywords:["expendable"],char:"♟",fitzpatrick_scale:false,category:"activity"},slot_machine:{keywords:["bet","gamble","vegas","fruit machine","luck","casino"],char:"🎰",fitzpatrick_scale:false,category:"activity"},jigsaw:{keywords:["interlocking","puzzle","piece"],char:"🧩",fitzpatrick_scale:false,category:"activity"},bowling:{keywords:["sports","fun","play"],char:"🎳",fitzpatrick_scale:false,category:"activity"},red_car:{keywords:["red","transportation","vehicle"],char:"🚗",fitzpatrick_scale:false,category:"travel_and_places"},taxi:{keywords:["uber","vehicle","cars","transportation"],char:"🚕",fitzpatrick_scale:false,category:"travel_and_places"},blue_car:{keywords:["transportation","vehicle"],char:"🚙",fitzpatrick_scale:false,category:"travel_and_places"},bus:{keywords:["car","vehicle","transportation"],char:"🚌",fitzpatrick_scale:false,category:"travel_and_places"},trolleybus:{keywords:["bart","transportation","vehicle"],char:"🚎",fitzpatrick_scale:false,category:"travel_and_places"},racing_car:{keywords:["sports","race","fast","formula","f1"],char:"🏎",fitzpatrick_scale:false,category:"travel_and_places"},police_car:{keywords:["vehicle","cars","transportation","law","legal","enforcement"],char:"🚓",fitzpatrick_scale:false,category:"travel_and_places"},ambulance:{keywords:["health","911","hospital"],char:"🚑",fitzpatrick_scale:false,category:"travel_and_places"},fire_engine:{keywords:["transportation","cars","vehicle"],char:"🚒",fitzpatrick_scale:false,category:"travel_and_places"},minibus:{keywords:["vehicle","car","transportation"],char:"🚐",fitzpatrick_scale:false,category:"travel_and_places"},truck:{keywords:["cars","transportation"],char:"🚚",fitzpatrick_scale:false,category:"travel_and_places"},articulated_lorry:{keywords:["vehicle","cars","transportation","express"],char:"🚛",fitzpatrick_scale:false,category:"travel_and_places"},tractor:{keywords:["vehicle","car","farming","agriculture"],char:"🚜",fitzpatrick_scale:false,category:"travel_and_places"},kick_scooter:{keywords:["vehicle","kick","razor"],char:"🛴",fitzpatrick_scale:false,category:"travel_and_places"},motorcycle:{keywords:["race","sports","fast"],char:"🏍",fitzpatrick_scale:false,category:"travel_and_places"},bike:{keywords:["sports","bicycle","exercise","hipster"],char:"🚲",fitzpatrick_scale:false,category:"travel_and_places"},motor_scooter:{keywords:["vehicle","vespa","sasha"],char:"🛵",fitzpatrick_scale:false,category:"travel_and_places"},rotating_light:{keywords:["police","ambulance","911","emergency","alert","error","pinged","law","legal"],char:"🚨",fitzpatrick_scale:false,category:"travel_and_places"},oncoming_police_car:{keywords:["vehicle","law","legal","enforcement","911"],char:"🚔",fitzpatrick_scale:false,category:"travel_and_places"},oncoming_bus:{keywords:["vehicle","transportation"],char:"🚍",fitzpatrick_scale:false,category:"travel_and_places"},oncoming_automobile:{keywords:["car","vehicle","transportation"],char:"🚘",fitzpatrick_scale:false,category:"travel_and_places"},oncoming_taxi:{keywords:["vehicle","cars","uber"],char:"🚖",fitzpatrick_scale:false,category:"travel_and_places"},aerial_tramway:{keywords:["transportation","vehicle","ski"],char:"🚡",fitzpatrick_scale:false,category:"travel_and_places"},mountain_cableway:{keywords:["transportation","vehicle","ski"],char:"🚠",fitzpatrick_scale:false,category:"travel_and_places"},suspension_railway:{keywords:["vehicle","transportation"],char:"🚟",fitzpatrick_scale:false,category:"travel_and_places"},railway_car:{keywords:["transportation","vehicle"],char:"🚃",fitzpatrick_scale:false,category:"travel_and_places"},train:{keywords:["transportation","vehicle","carriage","public","travel"],char:"🚋",fitzpatrick_scale:false,category:"travel_and_places"},monorail:{keywords:["transportation","vehicle"],char:"🚝",fitzpatrick_scale:false,category:"travel_and_places"},bullettrain_side:{keywords:["transportation","vehicle"],char:"🚄",fitzpatrick_scale:false,category:"travel_and_places"},bullettrain_front:{keywords:["transportation","vehicle","speed","fast","public","travel"],char:"🚅",fitzpatrick_scale:false,category:"travel_and_places"},light_rail:{keywords:["transportation","vehicle"],char:"🚈",fitzpatrick_scale:false,category:"travel_and_places"},mountain_railway:{keywords:["transportation","vehicle"],char:"🚞",fitzpatrick_scale:false,category:"travel_and_places"},steam_locomotive:{keywords:["transportation","vehicle","train"],char:"🚂",fitzpatrick_scale:false,category:"travel_and_places"},train2:{keywords:["transportation","vehicle"],char:"🚆",fitzpatrick_scale:false,category:"travel_and_places"},metro:{keywords:["transportation","blue-square","mrt","underground","tube"],char:"🚇",fitzpatrick_scale:false,category:"travel_and_places"},tram:{keywords:["transportation","vehicle"],char:"🚊",fitzpatrick_scale:false,category:"travel_and_places"},station:{keywords:["transportation","vehicle","public"],char:"🚉",fitzpatrick_scale:false,category:"travel_and_places"},flying_saucer:{keywords:["transportation","vehicle","ufo"],char:"🛸",fitzpatrick_scale:false,category:"travel_and_places"},helicopter:{keywords:["transportation","vehicle","fly"],char:"🚁",fitzpatrick_scale:false,category:"travel_and_places"},small_airplane:{keywords:["flight","transportation","fly","vehicle"],char:"🛩",fitzpatrick_scale:false,category:"travel_and_places"},airplane:{keywords:["vehicle","transportation","flight","fly"],char:"✈️",fitzpatrick_scale:false,category:"travel_and_places"},flight_departure:{keywords:["airport","flight","landing"],char:"🛫",fitzpatrick_scale:false,category:"travel_and_places"},flight_arrival:{keywords:["airport","flight","boarding"],char:"🛬",fitzpatrick_scale:false,category:"travel_and_places"},sailboat:{keywords:["ship","summer","transportation","water","sailing"],char:"⛵",fitzpatrick_scale:false,category:"travel_and_places"},motor_boat:{keywords:["ship"],char:"🛥",fitzpatrick_scale:false,category:"travel_and_places"},speedboat:{keywords:["ship","transportation","vehicle","summer"],char:"🚤",fitzpatrick_scale:false,category:"travel_and_places"},ferry:{keywords:["boat","ship","yacht"],char:"⛴",fitzpatrick_scale:false,category:"travel_and_places"},passenger_ship:{keywords:["yacht","cruise","ferry"],char:"🛳",fitzpatrick_scale:false,category:"travel_and_places"},rocket:{keywords:["launch","ship","staffmode","NASA","outer space","outer_space","fly"],char:"🚀",fitzpatrick_scale:false,category:"travel_and_places"},artificial_satellite:{keywords:["communication","gps","orbit","spaceflight","NASA","ISS"],char:"🛰",fitzpatrick_scale:false,category:"travel_and_places"},seat:{keywords:["sit","airplane","transport","bus","flight","fly"],char:"💺",fitzpatrick_scale:false,category:"travel_and_places"},canoe:{keywords:["boat","paddle","water","ship"],char:"🛶",fitzpatrick_scale:false,category:"travel_and_places"},anchor:{keywords:["ship","ferry","sea","boat"],char:"⚓",fitzpatrick_scale:false,category:"travel_and_places"},construction:{keywords:["wip","progress","caution","warning"],char:"🚧",fitzpatrick_scale:false,category:"travel_and_places"},fuelpump:{keywords:["gas station","petroleum"],char:"⛽",fitzpatrick_scale:false,category:"travel_and_places"},busstop:{keywords:["transportation","wait"],char:"🚏",fitzpatrick_scale:false,category:"travel_and_places"},vertical_traffic_light:{keywords:["transportation","driving"],char:"🚦",fitzpatrick_scale:false,category:"travel_and_places"},traffic_light:{keywords:["transportation","signal"],char:"🚥",fitzpatrick_scale:false,category:"travel_and_places"},checkered_flag:{keywords:["contest","finishline","race","gokart"],char:"🏁",fitzpatrick_scale:false,category:"travel_and_places"},ship:{keywords:["transportation","titanic","deploy"],char:"🚢",fitzpatrick_scale:false,category:"travel_and_places"},ferris_wheel:{keywords:["photo","carnival","londoneye"],char:"🎡",fitzpatrick_scale:false,category:"travel_and_places"},roller_coaster:{keywords:["carnival","playground","photo","fun"],char:"🎢",fitzpatrick_scale:false,category:"travel_and_places"},carousel_horse:{keywords:["photo","carnival"],char:"🎠",fitzpatrick_scale:false,category:"travel_and_places"},building_construction:{keywords:["wip","working","progress"],char:"🏗",fitzpatrick_scale:false,category:"travel_and_places"},foggy:{keywords:["photo","mountain"],char:"🌁",fitzpatrick_scale:false,category:"travel_and_places"},tokyo_tower:{keywords:["photo","japanese"],char:"🗼",fitzpatrick_scale:false,category:"travel_and_places"},factory:{keywords:["building","industry","pollution","smoke"],char:"🏭",fitzpatrick_scale:false,category:"travel_and_places"},fountain:{keywords:["photo","summer","water","fresh"],char:"⛲",fitzpatrick_scale:false,category:"travel_and_places"},rice_scene:{keywords:["photo","japan","asia","tsukimi"],char:"🎑",fitzpatrick_scale:false,category:"travel_and_places"},mountain:{keywords:["photo","nature","environment"],char:"⛰",fitzpatrick_scale:false,category:"travel_and_places"},mountain_snow:{keywords:["photo","nature","environment","winter","cold"],char:"🏔",fitzpatrick_scale:false,category:"travel_and_places"},mount_fuji:{keywords:["photo","mountain","nature","japanese"],char:"🗻",fitzpatrick_scale:false,category:"travel_and_places"},volcano:{keywords:["photo","nature","disaster"],char:"🌋",fitzpatrick_scale:false,category:"travel_and_places"},japan:{keywords:["nation","country","japanese","asia"],char:"🗾",fitzpatrick_scale:false,category:"travel_and_places"},camping:{keywords:["photo","outdoors","tent"],char:"🏕",fitzpatrick_scale:false,category:"travel_and_places"},tent:{keywords:["photo","camping","outdoors"],char:"⛺",fitzpatrick_scale:false,category:"travel_and_places"},national_park:{keywords:["photo","environment","nature"],char:"🏞",fitzpatrick_scale:false,category:"travel_and_places"},motorway:{keywords:["road","cupertino","interstate","highway"],char:"🛣",fitzpatrick_scale:false,category:"travel_and_places"},railway_track:{keywords:["train","transportation"],char:"🛤",fitzpatrick_scale:false,category:"travel_and_places"},sunrise:{keywords:["morning","view","vacation","photo"],char:"🌅",fitzpatrick_scale:false,category:"travel_and_places"},sunrise_over_mountains:{keywords:["view","vacation","photo"],char:"🌄",fitzpatrick_scale:false,category:"travel_and_places"},desert:{keywords:["photo","warm","saharah"],char:"🏜",fitzpatrick_scale:false,category:"travel_and_places"},beach_umbrella:{keywords:["weather","summer","sunny","sand","mojito"],char:"🏖",fitzpatrick_scale:false,category:"travel_and_places"},desert_island:{keywords:["photo","tropical","mojito"],char:"🏝",fitzpatrick_scale:false,category:"travel_and_places"},city_sunrise:{keywords:["photo","good morning","dawn"],char:"🌇",fitzpatrick_scale:false,category:"travel_and_places"},city_sunset:{keywords:["photo","evening","sky","buildings"],char:"🌆",fitzpatrick_scale:false,category:"travel_and_places"},cityscape:{keywords:["photo","night life","urban"],char:"🏙",fitzpatrick_scale:false,category:"travel_and_places"},night_with_stars:{keywords:["evening","city","downtown"],char:"🌃",fitzpatrick_scale:false,category:"travel_and_places"},bridge_at_night:{keywords:["photo","sanfrancisco"],char:"🌉",fitzpatrick_scale:false,category:"travel_and_places"},milky_way:{keywords:["photo","space","stars"],char:"🌌",fitzpatrick_scale:false,category:"travel_and_places"},stars:{keywords:["night","photo"],char:"🌠",fitzpatrick_scale:false,category:"travel_and_places"},sparkler:{keywords:["stars","night","shine"],char:"🎇",fitzpatrick_scale:false,category:"travel_and_places"},fireworks:{keywords:["photo","festival","carnival","congratulations"],char:"🎆",fitzpatrick_scale:false,category:"travel_and_places"},rainbow:{keywords:["nature","happy","unicorn_face","photo","sky","spring"],char:"🌈",fitzpatrick_scale:false,category:"travel_and_places"},houses:{keywords:["buildings","photo"],char:"🏘",fitzpatrick_scale:false,category:"travel_and_places"},european_castle:{keywords:["building","royalty","history"],char:"🏰",fitzpatrick_scale:false,category:"travel_and_places"},japanese_castle:{keywords:["photo","building"],char:"🏯",fitzpatrick_scale:false,category:"travel_and_places"},stadium:{keywords:["photo","place","sports","concert","venue"],char:"🏟",fitzpatrick_scale:false,category:"travel_and_places"},statue_of_liberty:{keywords:["american","newyork"],char:"🗽",fitzpatrick_scale:false,category:"travel_and_places"},house:{keywords:["building","home"],char:"🏠",fitzpatrick_scale:false,category:"travel_and_places"},house_with_garden:{keywords:["home","plant","nature"],char:"🏡",fitzpatrick_scale:false,category:"travel_and_places"},derelict_house:{keywords:["abandon","evict","broken","building"],char:"🏚",fitzpatrick_scale:false,category:"travel_and_places"},office:{keywords:["building","bureau","work"],char:"🏢",fitzpatrick_scale:false,category:"travel_and_places"},department_store:{keywords:["building","shopping","mall"],char:"🏬",fitzpatrick_scale:false,category:"travel_and_places"},post_office:{keywords:["building","envelope","communication"],char:"🏣",fitzpatrick_scale:false,category:"travel_and_places"},european_post_office:{keywords:["building","email"],char:"🏤",fitzpatrick_scale:false,category:"travel_and_places"},hospital:{keywords:["building","health","surgery","doctor"],char:"🏥",fitzpatrick_scale:false,category:"travel_and_places"},bank:{keywords:["building","money","sales","cash","business","enterprise"],char:"🏦",fitzpatrick_scale:false,category:"travel_and_places"},hotel:{keywords:["building","accomodation","checkin"],char:"🏨",fitzpatrick_scale:false,category:"travel_and_places"},convenience_store:{keywords:["building","shopping","groceries"],char:"🏪",fitzpatrick_scale:false,category:"travel_and_places"},school:{keywords:["building","student","education","learn","teach"],char:"🏫",fitzpatrick_scale:false,category:"travel_and_places"},love_hotel:{keywords:["like","affection","dating"],char:"🏩",fitzpatrick_scale:false,category:"travel_and_places"},wedding:{keywords:["love","like","affection","couple","marriage","bride","groom"],char:"💒",fitzpatrick_scale:false,category:"travel_and_places"},classical_building:{keywords:["art","culture","history"],char:"🏛",fitzpatrick_scale:false,category:"travel_and_places"},church:{keywords:["building","religion","christ"],char:"⛪",fitzpatrick_scale:false,category:"travel_and_places"},mosque:{keywords:["islam","worship","minaret"],char:"🕌",fitzpatrick_scale:false,category:"travel_and_places"},synagogue:{keywords:["judaism","worship","temple","jewish"],char:"🕍",fitzpatrick_scale:false,category:"travel_and_places"},kaaba:{keywords:["mecca","mosque","islam"],char:"🕋",fitzpatrick_scale:false,category:"travel_and_places"},shinto_shrine:{keywords:["temple","japan","kyoto"],char:"⛩",fitzpatrick_scale:false,category:"travel_and_places"},watch:{keywords:["time","accessories"],char:"⌚",fitzpatrick_scale:false,category:"objects"},iphone:{keywords:["technology","apple","gadgets","dial"],char:"📱",fitzpatrick_scale:false,category:"objects"},calling:{keywords:["iphone","incoming"],char:"📲",fitzpatrick_scale:false,category:"objects"},computer:{keywords:["technology","laptop","screen","display","monitor"],char:"💻",fitzpatrick_scale:false,category:"objects"},keyboard:{keywords:["technology","computer","type","input","text"],char:"⌨",fitzpatrick_scale:false,category:"objects"},desktop_computer:{keywords:["technology","computing","screen"],char:"🖥",fitzpatrick_scale:false,category:"objects"},printer:{keywords:["paper","ink"],char:"🖨",fitzpatrick_scale:false,category:"objects"},computer_mouse:{keywords:["click"],char:"🖱",fitzpatrick_scale:false,category:"objects"},trackball:{keywords:["technology","trackpad"],char:"🖲",fitzpatrick_scale:false,category:"objects"},joystick:{keywords:["game","play"],char:"🕹",fitzpatrick_scale:false,category:"objects"},clamp:{keywords:["tool"],char:"🗜",fitzpatrick_scale:false,category:"objects"},minidisc:{keywords:["technology","record","data","disk","90s"],char:"💽",fitzpatrick_scale:false,category:"objects"},floppy_disk:{keywords:["oldschool","technology","save","90s","80s"],char:"💾",fitzpatrick_scale:false,category:"objects"},cd:{keywords:["technology","dvd","disk","disc","90s"],char:"💿",fitzpatrick_scale:false,category:"objects"},dvd:{keywords:["cd","disk","disc"],char:"📀",fitzpatrick_scale:false,category:"objects"},vhs:{keywords:["record","video","oldschool","90s","80s"],char:"📼",fitzpatrick_scale:false,category:"objects"},camera:{keywords:["gadgets","photography"],char:"📷",fitzpatrick_scale:false,category:"objects"},camera_flash:{keywords:["photography","gadgets"],char:"📸",fitzpatrick_scale:false,category:"objects"},video_camera:{keywords:["film","record"],char:"📹",fitzpatrick_scale:false,category:"objects"},movie_camera:{keywords:["film","record"],char:"🎥",fitzpatrick_scale:false,category:"objects"},film_projector:{keywords:["video","tape","record","movie"],char:"📽",fitzpatrick_scale:false,category:"objects"},film_strip:{keywords:["movie"],char:"🎞",fitzpatrick_scale:false,category:"objects"},telephone_receiver:{keywords:["technology","communication","dial"],char:"📞",fitzpatrick_scale:false,category:"objects"},phone:{keywords:["technology","communication","dial","telephone"],char:"☎️",fitzpatrick_scale:false,category:"objects"},pager:{keywords:["bbcall","oldschool","90s"],char:"📟",fitzpatrick_scale:false,category:"objects"},fax:{keywords:["communication","technology"],char:"📠",fitzpatrick_scale:false,category:"objects"},tv:{keywords:["technology","program","oldschool","show","television"],char:"📺",fitzpatrick_scale:false,category:"objects"},radio:{keywords:["communication","music","podcast","program"],char:"📻",fitzpatrick_scale:false,category:"objects"},studio_microphone:{keywords:["sing","recording","artist","talkshow"],char:"🎙",fitzpatrick_scale:false,category:"objects"},level_slider:{keywords:["scale"],char:"🎚",fitzpatrick_scale:false,category:"objects"},control_knobs:{keywords:["dial"],char:"🎛",fitzpatrick_scale:false,category:"objects"},compass:{keywords:["magnetic","navigation","orienteering"],char:"🧭",fitzpatrick_scale:false,category:"objects"},stopwatch:{keywords:["time","deadline"],char:"⏱",fitzpatrick_scale:false,category:"objects"},timer_clock:{keywords:["alarm"],char:"⏲",fitzpatrick_scale:false,category:"objects"},alarm_clock:{keywords:["time","wake"],char:"⏰",fitzpatrick_scale:false,category:"objects"},mantelpiece_clock:{keywords:["time"],char:"🕰",fitzpatrick_scale:false,category:"objects"},hourglass_flowing_sand:{keywords:["oldschool","time","countdown"],char:"⏳",fitzpatrick_scale:false,category:"objects"},hourglass:{keywords:["time","clock","oldschool","limit","exam","quiz","test"],char:"⌛",fitzpatrick_scale:false,category:"objects"},satellite:{keywords:["communication","future","radio","space"],char:"📡",fitzpatrick_scale:false,category:"objects"},battery:{keywords:["power","energy","sustain"],char:"🔋",fitzpatrick_scale:false,category:"objects"},electric_plug:{keywords:["charger","power"],char:"🔌",fitzpatrick_scale:false,category:"objects"},bulb:{keywords:["light","electricity","idea"],char:"💡",fitzpatrick_scale:false,category:"objects"},flashlight:{keywords:["dark","camping","sight","night"],char:"🔦",fitzpatrick_scale:false,category:"objects"},candle:{keywords:["fire","wax"],char:"🕯",fitzpatrick_scale:false,category:"objects"},fire_extinguisher:{keywords:["quench"],char:"🧯",fitzpatrick_scale:false,category:"objects"},wastebasket:{keywords:["bin","trash","rubbish","garbage","toss"],char:"🗑",fitzpatrick_scale:false,category:"objects"},oil_drum:{keywords:["barrell"],char:"🛢",fitzpatrick_scale:false,category:"objects"},money_with_wings:{keywords:["dollar","bills","payment","sale"],char:"💸",fitzpatrick_scale:false,category:"objects"},dollar:{keywords:["money","sales","bill","currency"],char:"💵",fitzpatrick_scale:false,category:"objects"},yen:{keywords:["money","sales","japanese","dollar","currency"],char:"💴",fitzpatrick_scale:false,category:"objects"},euro:{keywords:["money","sales","dollar","currency"],char:"💶",fitzpatrick_scale:false,category:"objects"},pound:{keywords:["british","sterling","money","sales","bills","uk","england","currency"],char:"💷",fitzpatrick_scale:false,category:"objects"},moneybag:{keywords:["dollar","payment","coins","sale"],char:"💰",fitzpatrick_scale:false,category:"objects"},credit_card:{keywords:["money","sales","dollar","bill","payment","shopping"],char:"💳",fitzpatrick_scale:false,category:"objects"},gem:{keywords:["blue","ruby","diamond","jewelry"],char:"💎",fitzpatrick_scale:false,category:"objects"},balance_scale:{keywords:["law","fairness","weight"],char:"⚖",fitzpatrick_scale:false,category:"objects"},toolbox:{keywords:["tools","diy","fix","maintainer","mechanic"],char:"🧰",fitzpatrick_scale:false,category:"objects"},wrench:{keywords:["tools","diy","ikea","fix","maintainer"],char:"🔧",fitzpatrick_scale:false,category:"objects"},hammer:{keywords:["tools","build","create"],char:"🔨",fitzpatrick_scale:false,category:"objects"},hammer_and_pick:{keywords:["tools","build","create"],char:"⚒",fitzpatrick_scale:false,category:"objects"},hammer_and_wrench:{keywords:["tools","build","create"],char:"🛠",fitzpatrick_scale:false,category:"objects"},pick:{keywords:["tools","dig"],char:"⛏",fitzpatrick_scale:false,category:"objects"},nut_and_bolt:{keywords:["handy","tools","fix"],char:"🔩",fitzpatrick_scale:false,category:"objects"},gear:{keywords:["cog"],char:"⚙",fitzpatrick_scale:false,category:"objects"},brick:{keywords:["bricks"],char:"🧱",fitzpatrick_scale:false,category:"objects"},chains:{keywords:["lock","arrest"],char:"⛓",fitzpatrick_scale:false,category:"objects"},magnet:{keywords:["attraction","magnetic"],char:"🧲",fitzpatrick_scale:false,category:"objects"},gun:{keywords:["violence","weapon","pistol","revolver"],char:"🔫",fitzpatrick_scale:false,category:"objects"},bomb:{keywords:["boom","explode","explosion","terrorism"],char:"💣",fitzpatrick_scale:false,category:"objects"},firecracker:{keywords:["dynamite","boom","explode","explosion","explosive"],char:"🧨",fitzpatrick_scale:false,category:"objects"},hocho:{keywords:["knife","blade","cutlery","kitchen","weapon"],char:"🔪",fitzpatrick_scale:false,category:"objects"},dagger:{keywords:["weapon"],char:"🗡",fitzpatrick_scale:false,category:"objects"},crossed_swords:{keywords:["weapon"],char:"⚔",fitzpatrick_scale:false,category:"objects"},shield:{keywords:["protection","security"],char:"🛡",fitzpatrick_scale:false,category:"objects"},smoking:{keywords:["kills","tobacco","cigarette","joint","smoke"],char:"🚬",fitzpatrick_scale:false,category:"objects"},skull_and_crossbones:{keywords:["poison","danger","deadly","scary","death","pirate","evil"],char:"☠",fitzpatrick_scale:false,category:"objects"},coffin:{keywords:["vampire","dead","die","death","rip","graveyard","cemetery","casket","funeral","box"],char:"⚰",fitzpatrick_scale:false,category:"objects"},funeral_urn:{keywords:["dead","die","death","rip","ashes"],char:"⚱",fitzpatrick_scale:false,category:"objects"},amphora:{keywords:["vase","jar"],char:"🏺",fitzpatrick_scale:false,category:"objects"},crystal_ball:{keywords:["disco","party","magic","circus","fortune_teller"],char:"🔮",fitzpatrick_scale:false,category:"objects"},prayer_beads:{keywords:["dhikr","religious"],char:"📿",fitzpatrick_scale:false,category:"objects"},nazar_amulet:{keywords:["bead","charm"],char:"🧿",fitzpatrick_scale:false,category:"objects"},barber:{keywords:["hair","salon","style"],char:"💈",fitzpatrick_scale:false,category:"objects"},alembic:{keywords:["distilling","science","experiment","chemistry"],char:"⚗",fitzpatrick_scale:false,category:"objects"},telescope:{keywords:["stars","space","zoom","science","astronomy"],char:"🔭",fitzpatrick_scale:false,category:"objects"},microscope:{keywords:["laboratory","experiment","zoomin","science","study"],char:"🔬",fitzpatrick_scale:false,category:"objects"},hole:{keywords:["embarrassing"],char:"🕳",fitzpatrick_scale:false,category:"objects"},pill:{keywords:["health","medicine","doctor","pharmacy","drug"],char:"💊",fitzpatrick_scale:false,category:"objects"},syringe:{keywords:["health","hospital","drugs","blood","medicine","needle","doctor","nurse"],char:"💉",fitzpatrick_scale:false,category:"objects"},dna:{keywords:["biologist","genetics","life"],char:"🧬",fitzpatrick_scale:false,category:"objects"},microbe:{keywords:["amoeba","bacteria","germs"],char:"🦠",fitzpatrick_scale:false,category:"objects"},petri_dish:{keywords:["bacteria","biology","culture","lab"],char:"🧫",fitzpatrick_scale:false,category:"objects"},test_tube:{keywords:["chemistry","experiment","lab","science"],char:"🧪",fitzpatrick_scale:false,category:"objects"},thermometer:{keywords:["weather","temperature","hot","cold"],char:"🌡",fitzpatrick_scale:false,category:"objects"},broom:{keywords:["cleaning","sweeping","witch"],char:"🧹",fitzpatrick_scale:false,category:"objects"},basket:{keywords:["laundry"],char:"🧺",fitzpatrick_scale:false,category:"objects"},toilet_paper:{keywords:["roll"],char:"🧻",fitzpatrick_scale:false,category:"objects"},label:{keywords:["sale","tag"],char:"🏷",fitzpatrick_scale:false,category:"objects"},bookmark:{keywords:["favorite","label","save"],char:"🔖",fitzpatrick_scale:false,category:"objects"},toilet:{keywords:["restroom","wc","washroom","bathroom","potty"],char:"🚽",fitzpatrick_scale:false,category:"objects"},shower:{keywords:["clean","water","bathroom"],char:"🚿",fitzpatrick_scale:false,category:"objects"},bathtub:{keywords:["clean","shower","bathroom"],char:"🛁",fitzpatrick_scale:false,category:"objects"},soap:{keywords:["bar","bathing","cleaning","lather"],char:"🧼",fitzpatrick_scale:false,category:"objects"},sponge:{keywords:["absorbing","cleaning","porous"],char:"🧽",fitzpatrick_scale:false,category:"objects"},lotion_bottle:{keywords:["moisturizer","sunscreen"],char:"🧴",fitzpatrick_scale:false,category:"objects"},key:{keywords:["lock","door","password"],char:"🔑",fitzpatrick_scale:false,category:"objects"},old_key:{keywords:["lock","door","password"],char:"🗝",fitzpatrick_scale:false,category:"objects"},couch_and_lamp:{keywords:["read","chill"],char:"🛋",fitzpatrick_scale:false,category:"objects"},sleeping_bed:{keywords:["bed","rest"],char:"🛌",fitzpatrick_scale:true,category:"objects"},bed:{keywords:["sleep","rest"],char:"🛏",fitzpatrick_scale:false,category:"objects"},door:{keywords:["house","entry","exit"],char:"🚪",fitzpatrick_scale:false,category:"objects"},bellhop_bell:{keywords:["service"],char:"🛎",fitzpatrick_scale:false,category:"objects"},teddy_bear:{keywords:["plush","stuffed"],char:"🧸",fitzpatrick_scale:false,category:"objects"},framed_picture:{keywords:["photography"],char:"🖼",fitzpatrick_scale:false,category:"objects"},world_map:{keywords:["location","direction"],char:"🗺",fitzpatrick_scale:false,category:"objects"},parasol_on_ground:{keywords:["weather","summer"],char:"⛱",fitzpatrick_scale:false,category:"objects"},moyai:{keywords:["rock","easter island","moai"],char:"🗿",fitzpatrick_scale:false,category:"objects"},shopping:{keywords:["mall","buy","purchase"],char:"🛍",fitzpatrick_scale:false,category:"objects"},shopping_cart:{keywords:["trolley"],char:"🛒",fitzpatrick_scale:false,category:"objects"},balloon:{keywords:["party","celebration","birthday","circus"],char:"🎈",fitzpatrick_scale:false,category:"objects"},flags:{keywords:["fish","japanese","koinobori","carp","banner"],char:"🎏",fitzpatrick_scale:false,category:"objects"},ribbon:{keywords:["decoration","pink","girl","bowtie"],char:"🎀",fitzpatrick_scale:false,category:"objects"},gift:{keywords:["present","birthday","christmas","xmas"],char:"🎁",fitzpatrick_scale:false,category:"objects"},confetti_ball:{keywords:["festival","party","birthday","circus"],char:"🎊",fitzpatrick_scale:false,category:"objects"},tada:{keywords:["party","congratulations","birthday","magic","circus","celebration"],char:"🎉",fitzpatrick_scale:false,category:"objects"},dolls:{keywords:["japanese","toy","kimono"],char:"🎎",fitzpatrick_scale:false,category:"objects"},wind_chime:{keywords:["nature","ding","spring","bell"],char:"🎐",fitzpatrick_scale:false,category:"objects"},crossed_flags:{keywords:["japanese","nation","country","border"],char:"🎌",fitzpatrick_scale:false,category:"objects"},izakaya_lantern:{keywords:["light","paper","halloween","spooky"],char:"🏮",fitzpatrick_scale:false,category:"objects"},red_envelope:{keywords:["gift"],char:"🧧",fitzpatrick_scale:false,category:"objects"},email:{keywords:["letter","postal","inbox","communication"],char:"✉️",fitzpatrick_scale:false,category:"objects"},envelope_with_arrow:{keywords:["email","communication"],char:"📩",fitzpatrick_scale:false,category:"objects"},incoming_envelope:{keywords:["email","inbox"],char:"📨",fitzpatrick_scale:false,category:"objects"},"e-mail":{keywords:["communication","inbox"],char:"📧",fitzpatrick_scale:false,category:"objects"},love_letter:{keywords:["email","like","affection","envelope","valentines"],char:"💌",fitzpatrick_scale:false,category:"objects"},postbox:{keywords:["email","letter","envelope"],char:"📮",fitzpatrick_scale:false,category:"objects"},mailbox_closed:{keywords:["email","communication","inbox"],char:"📪",fitzpatrick_scale:false,category:"objects"},mailbox:{keywords:["email","inbox","communication"],char:"📫",fitzpatrick_scale:false,category:"objects"},mailbox_with_mail:{keywords:["email","inbox","communication"],char:"📬",fitzpatrick_scale:false,category:"objects"},mailbox_with_no_mail:{keywords:["email","inbox"],char:"📭",fitzpatrick_scale:false,category:"objects"},package:{keywords:["mail","gift","cardboard","box","moving"],char:"📦",fitzpatrick_scale:false,category:"objects"},postal_horn:{keywords:["instrument","music"],char:"📯",fitzpatrick_scale:false,category:"objects"},inbox_tray:{keywords:["email","documents"],char:"📥",fitzpatrick_scale:false,category:"objects"},outbox_tray:{keywords:["inbox","email"],char:"📤",fitzpatrick_scale:false,category:"objects"},scroll:{keywords:["documents","ancient","history","paper"],char:"📜",fitzpatrick_scale:false,category:"objects"},page_with_curl:{keywords:["documents","office","paper"],char:"📃",fitzpatrick_scale:false,category:"objects"},bookmark_tabs:{keywords:["favorite","save","order","tidy"],char:"📑",fitzpatrick_scale:false,category:"objects"},receipt:{keywords:["accounting","expenses"],char:"🧾",fitzpatrick_scale:false,category:"objects"},bar_chart:{keywords:["graph","presentation","stats"],char:"📊",fitzpatrick_scale:false,category:"objects"},chart_with_upwards_trend:{keywords:["graph","presentation","stats","recovery","business","economics","money","sales","good","success"],char:"📈",fitzpatrick_scale:false,category:"objects"},chart_with_downwards_trend:{keywords:["graph","presentation","stats","recession","business","economics","money","sales","bad","failure"],char:"📉",fitzpatrick_scale:false,category:"objects"},page_facing_up:{keywords:["documents","office","paper","information"],char:"📄",fitzpatrick_scale:false,category:"objects"},date:{keywords:["calendar","schedule"],char:"📅",fitzpatrick_scale:false,category:"objects"},calendar:{keywords:["schedule","date","planning"],char:"📆",fitzpatrick_scale:false,category:"objects"},spiral_calendar:{keywords:["date","schedule","planning"],char:"🗓",fitzpatrick_scale:false,category:"objects"},card_index:{keywords:["business","stationery"],char:"📇",fitzpatrick_scale:false,category:"objects"},card_file_box:{keywords:["business","stationery"],char:"🗃",fitzpatrick_scale:false,category:"objects"},ballot_box:{keywords:["election","vote"],char:"🗳",fitzpatrick_scale:false,category:"objects"},file_cabinet:{keywords:["filing","organizing"],char:"🗄",fitzpatrick_scale:false,category:"objects"},clipboard:{keywords:["stationery","documents"],char:"📋",fitzpatrick_scale:false,category:"objects"},spiral_notepad:{keywords:["memo","stationery"],char:"🗒",fitzpatrick_scale:false,category:"objects"},file_folder:{keywords:["documents","business","office"],char:"📁",fitzpatrick_scale:false,category:"objects"},open_file_folder:{keywords:["documents","load"],char:"📂",fitzpatrick_scale:false,category:"objects"},card_index_dividers:{keywords:["organizing","business","stationery"],char:"🗂",fitzpatrick_scale:false,category:"objects"},newspaper_roll:{keywords:["press","headline"],char:"🗞",fitzpatrick_scale:false,category:"objects"},newspaper:{keywords:["press","headline"],char:"📰",fitzpatrick_scale:false,category:"objects"},notebook:{keywords:["stationery","record","notes","paper","study"],char:"📓",fitzpatrick_scale:false,category:"objects"},closed_book:{keywords:["read","library","knowledge","textbook","learn"],char:"📕",fitzpatrick_scale:false,category:"objects"},green_book:{keywords:["read","library","knowledge","study"],char:"📗",fitzpatrick_scale:false,category:"objects"},blue_book:{keywords:["read","library","knowledge","learn","study"],char:"📘",fitzpatrick_scale:false,category:"objects"},orange_book:{keywords:["read","library","knowledge","textbook","study"],char:"📙",fitzpatrick_scale:false,category:"objects"},notebook_with_decorative_cover:{keywords:["classroom","notes","record","paper","study"],char:"📔",fitzpatrick_scale:false,category:"objects"},ledger:{keywords:["notes","paper"],char:"📒",fitzpatrick_scale:false,category:"objects"},books:{keywords:["literature","library","study"],char:"📚",fitzpatrick_scale:false,category:"objects"},open_book:{keywords:["book","read","library","knowledge","literature","learn","study"],char:"📖",fitzpatrick_scale:false,category:"objects"},safety_pin:{keywords:["diaper"],char:"🧷",fitzpatrick_scale:false,category:"objects"},link:{keywords:["rings","url"],char:"🔗",fitzpatrick_scale:false,category:"objects"},paperclip:{keywords:["documents","stationery"],char:"📎",fitzpatrick_scale:false,category:"objects"},paperclips:{keywords:["documents","stationery"],char:"🖇",fitzpatrick_scale:false,category:"objects"},scissors:{keywords:["stationery","cut"],char:"✂️",fitzpatrick_scale:false,category:"objects"},triangular_ruler:{keywords:["stationery","math","architect","sketch"],char:"📐",fitzpatrick_scale:false,category:"objects"},straight_ruler:{keywords:["stationery","calculate","length","math","school","drawing","architect","sketch"],char:"📏",fitzpatrick_scale:false,category:"objects"},abacus:{keywords:["calculation"],char:"🧮",fitzpatrick_scale:false,category:"objects"},pushpin:{keywords:["stationery","mark","here"],char:"📌",fitzpatrick_scale:false,category:"objects"},round_pushpin:{keywords:["stationery","location","map","here"],char:"📍",fitzpatrick_scale:false,category:"objects"},triangular_flag_on_post:{keywords:["mark","milestone","place"],char:"🚩",fitzpatrick_scale:false,category:"objects"},white_flag:{keywords:["losing","loser","lost","surrender","give up","fail"],char:"🏳",fitzpatrick_scale:false,category:"objects"},black_flag:{keywords:["pirate"],char:"🏴",fitzpatrick_scale:false,category:"objects"},rainbow_flag:{keywords:["flag","rainbow","pride","gay","lgbt","glbt","queer","homosexual","lesbian","bisexual","transgender"],char:"🏳️‍🌈",fitzpatrick_scale:false,category:"objects"},closed_lock_with_key:{keywords:["security","privacy"],char:"🔐",fitzpatrick_scale:false,category:"objects"},lock:{keywords:["security","password","padlock"],char:"🔒",fitzpatrick_scale:false,category:"objects"},unlock:{keywords:["privacy","security"],char:"🔓",fitzpatrick_scale:false,category:"objects"},lock_with_ink_pen:{keywords:["security","secret"],char:"🔏",fitzpatrick_scale:false,category:"objects"},pen:{keywords:["stationery","writing","write"],char:"🖊",fitzpatrick_scale:false,category:"objects"},fountain_pen:{keywords:["stationery","writing","write"],char:"🖋",fitzpatrick_scale:false,category:"objects"},black_nib:{keywords:["pen","stationery","writing","write"],char:"✒️",fitzpatrick_scale:false,category:"objects"},memo:{keywords:["write","documents","stationery","pencil","paper","writing","legal","exam","quiz","test","study","compose"],char:"📝",fitzpatrick_scale:false,category:"objects"},pencil2:{keywords:["stationery","write","paper","writing","school","study"],char:"✏️",fitzpatrick_scale:false,category:"objects"},crayon:{keywords:["drawing","creativity"],char:"🖍",fitzpatrick_scale:false,category:"objects"},paintbrush:{keywords:["drawing","creativity","art"],char:"🖌",fitzpatrick_scale:false,category:"objects"},mag:{keywords:["search","zoom","find","detective"],char:"🔍",fitzpatrick_scale:false,category:"objects"},mag_right:{keywords:["search","zoom","find","detective"],char:"🔎",fitzpatrick_scale:false,category:"objects"},heart:{keywords:["love","like","valentines"],char:"❤️",fitzpatrick_scale:false,category:"symbols"},orange_heart:{keywords:["love","like","affection","valentines"],char:"🧡",fitzpatrick_scale:false,category:"symbols"},yellow_heart:{keywords:["love","like","affection","valentines"],char:"💛",fitzpatrick_scale:false,category:"symbols"},green_heart:{keywords:["love","like","affection","valentines"],char:"💚",fitzpatrick_scale:false,category:"symbols"},blue_heart:{keywords:["love","like","affection","valentines"],char:"💙",fitzpatrick_scale:false,category:"symbols"},purple_heart:{keywords:["love","like","affection","valentines"],char:"💜",fitzpatrick_scale:false,category:"symbols"},black_heart:{keywords:["evil"],char:"🖤",fitzpatrick_scale:false,category:"symbols"},broken_heart:{keywords:["sad","sorry","break","heart","heartbreak"],char:"💔",fitzpatrick_scale:false,category:"symbols"},heavy_heart_exclamation:{keywords:["decoration","love"],char:"❣",fitzpatrick_scale:false,category:"symbols"},two_hearts:{keywords:["love","like","affection","valentines","heart"],char:"💕",fitzpatrick_scale:false,category:"symbols"},revolving_hearts:{keywords:["love","like","affection","valentines"],char:"💞",fitzpatrick_scale:false,category:"symbols"},heartbeat:{keywords:["love","like","affection","valentines","pink","heart"],char:"💓",fitzpatrick_scale:false,category:"symbols"},heartpulse:{keywords:["like","love","affection","valentines","pink"],char:"💗",fitzpatrick_scale:false,category:"symbols"},sparkling_heart:{keywords:["love","like","affection","valentines"],char:"💖",fitzpatrick_scale:false,category:"symbols"},cupid:{keywords:["love","like","heart","affection","valentines"],char:"💘",fitzpatrick_scale:false,category:"symbols"},gift_heart:{keywords:["love","valentines"],char:"💝",fitzpatrick_scale:false,category:"symbols"},heart_decoration:{keywords:["purple-square","love","like"],char:"💟",fitzpatrick_scale:false,category:"symbols"},peace_symbol:{keywords:["hippie"],char:"☮",fitzpatrick_scale:false,category:"symbols"},latin_cross:{keywords:["christianity"],char:"✝",fitzpatrick_scale:false,category:"symbols"},star_and_crescent:{keywords:["islam"],char:"☪",fitzpatrick_scale:false,category:"symbols"},om:{keywords:["hinduism","buddhism","sikhism","jainism"],char:"🕉",fitzpatrick_scale:false,category:"symbols"},wheel_of_dharma:{keywords:["hinduism","buddhism","sikhism","jainism"],char:"☸",fitzpatrick_scale:false,category:"symbols"},star_of_david:{keywords:["judaism"],char:"✡",fitzpatrick_scale:false,category:"symbols"},six_pointed_star:{keywords:["purple-square","religion","jewish","hexagram"],char:"🔯",fitzpatrick_scale:false,category:"symbols"},menorah:{keywords:["hanukkah","candles","jewish"],char:"🕎",fitzpatrick_scale:false,category:"symbols"},yin_yang:{keywords:["balance"],char:"☯",fitzpatrick_scale:false,category:"symbols"},orthodox_cross:{keywords:["suppedaneum","religion"],char:"☦",fitzpatrick_scale:false,category:"symbols"},place_of_worship:{keywords:["religion","church","temple","prayer"],char:"🛐",fitzpatrick_scale:false,category:"symbols"},ophiuchus:{keywords:["sign","purple-square","constellation","astrology"],char:"⛎",fitzpatrick_scale:false,category:"symbols"},aries:{keywords:["sign","purple-square","zodiac","astrology"],char:"♈",fitzpatrick_scale:false,category:"symbols"},taurus:{keywords:["purple-square","sign","zodiac","astrology"],char:"♉",fitzpatrick_scale:false,category:"symbols"},gemini:{keywords:["sign","zodiac","purple-square","astrology"],char:"♊",fitzpatrick_scale:false,category:"symbols"},cancer:{keywords:["sign","zodiac","purple-square","astrology"],char:"♋",fitzpatrick_scale:false,category:"symbols"},leo:{keywords:["sign","purple-square","zodiac","astrology"],char:"♌",fitzpatrick_scale:false,category:"symbols"},virgo:{keywords:["sign","zodiac","purple-square","astrology"],char:"♍",fitzpatrick_scale:false,category:"symbols"},libra:{keywords:["sign","purple-square","zodiac","astrology"],char:"♎",fitzpatrick_scale:false,category:"symbols"},scorpius:{keywords:["sign","zodiac","purple-square","astrology","scorpio"],char:"♏",fitzpatrick_scale:false,category:"symbols"},sagittarius:{keywords:["sign","zodiac","purple-square","astrology"],char:"♐",fitzpatrick_scale:false,category:"symbols"},capricorn:{keywords:["sign","zodiac","purple-square","astrology"],char:"♑",fitzpatrick_scale:false,category:"symbols"},aquarius:{keywords:["sign","purple-square","zodiac","astrology"],char:"♒",fitzpatrick_scale:false,category:"symbols"},pisces:{keywords:["purple-square","sign","zodiac","astrology"],char:"♓",fitzpatrick_scale:false,category:"symbols"},id:{keywords:["purple-square","words"],char:"🆔",fitzpatrick_scale:false,category:"symbols"},atom_symbol:{keywords:["science","physics","chemistry"],char:"⚛",fitzpatrick_scale:false,category:"symbols"},u7a7a:{keywords:["kanji","japanese","chinese","empty","sky","blue-square"],char:"🈳",fitzpatrick_scale:false,category:"symbols"},u5272:{keywords:["cut","divide","chinese","kanji","pink-square"],char:"🈹",fitzpatrick_scale:false,category:"symbols"},radioactive:{keywords:["nuclear","danger"],char:"☢",fitzpatrick_scale:false,category:"symbols"},biohazard:{keywords:["danger"],char:"☣",fitzpatrick_scale:false,category:"symbols"},mobile_phone_off:{keywords:["mute","orange-square","silence","quiet"],char:"📴",fitzpatrick_scale:false,category:"symbols"},vibration_mode:{keywords:["orange-square","phone"],char:"📳",fitzpatrick_scale:false,category:"symbols"},u6709:{keywords:["orange-square","chinese","have","kanji"],char:"🈶",fitzpatrick_scale:false,category:"symbols"},u7121:{keywords:["nothing","chinese","kanji","japanese","orange-square"],char:"🈚",fitzpatrick_scale:false,category:"symbols"},u7533:{keywords:["chinese","japanese","kanji","orange-square"],char:"🈸",fitzpatrick_scale:false,category:"symbols"},u55b6:{keywords:["japanese","opening hours","orange-square"],char:"🈺",fitzpatrick_scale:false,category:"symbols"},u6708:{keywords:["chinese","month","moon","japanese","orange-square","kanji"],char:"🈷️",fitzpatrick_scale:false,category:"symbols"},eight_pointed_black_star:{keywords:["orange-square","shape","polygon"],char:"✴️",fitzpatrick_scale:false,category:"symbols"},vs:{keywords:["words","orange-square"],char:"🆚",fitzpatrick_scale:false,category:"symbols"},accept:{keywords:["ok","good","chinese","kanji","agree","yes","orange-circle"],char:"🉑",fitzpatrick_scale:false,category:"symbols"},white_flower:{keywords:["japanese","spring"],char:"💮",fitzpatrick_scale:false,category:"symbols"},ideograph_advantage:{keywords:["chinese","kanji","obtain","get","circle"],char:"🉐",fitzpatrick_scale:false,category:"symbols"},secret:{keywords:["privacy","chinese","sshh","kanji","red-circle"],char:"㊙️",fitzpatrick_scale:false,category:"symbols"},congratulations:{keywords:["chinese","kanji","japanese","red-circle"],char:"㊗️",fitzpatrick_scale:false,category:"symbols"},u5408:{keywords:["japanese","chinese","join","kanji","red-square"],char:"🈴",fitzpatrick_scale:false,category:"symbols"},u6e80:{keywords:["full","chinese","japanese","red-square","kanji"],char:"🈵",fitzpatrick_scale:false,category:"symbols"},u7981:{keywords:["kanji","japanese","chinese","forbidden","limit","restricted","red-square"],char:"🈲",fitzpatrick_scale:false,category:"symbols"},a:{keywords:["red-square","alphabet","letter"],char:"🅰️",fitzpatrick_scale:false,category:"symbols"},b:{keywords:["red-square","alphabet","letter"],char:"🅱️",fitzpatrick_scale:false,category:"symbols"},ab:{keywords:["red-square","alphabet"],char:"🆎",fitzpatrick_scale:false,category:"symbols"},cl:{keywords:["alphabet","words","red-square"],char:"🆑",fitzpatrick_scale:false,category:"symbols"},o2:{keywords:["alphabet","red-square","letter"],char:"🅾️",fitzpatrick_scale:false,category:"symbols"},sos:{keywords:["help","red-square","words","emergency","911"],char:"🆘",fitzpatrick_scale:false,category:"symbols"},no_entry:{keywords:["limit","security","privacy","bad","denied","stop","circle"],char:"⛔",fitzpatrick_scale:false,category:"symbols"},name_badge:{keywords:["fire","forbid"],char:"📛",fitzpatrick_scale:false,category:"symbols"},no_entry_sign:{keywords:["forbid","stop","limit","denied","disallow","circle"],char:"🚫",fitzpatrick_scale:false,category:"symbols"},x:{keywords:["no","delete","remove","cancel","red"],char:"❌",fitzpatrick_scale:false,category:"symbols"},o:{keywords:["circle","round"],char:"⭕",fitzpatrick_scale:false,category:"symbols"},stop_sign:{keywords:["stop"],char:"🛑",fitzpatrick_scale:false,category:"symbols"},anger:{keywords:["angry","mad"],char:"💢",fitzpatrick_scale:false,category:"symbols"},hotsprings:{keywords:["bath","warm","relax"],char:"♨️",fitzpatrick_scale:false,category:"symbols"},no_pedestrians:{keywords:["rules","crossing","walking","circle"],char:"🚷",fitzpatrick_scale:false,category:"symbols"},do_not_litter:{keywords:["trash","bin","garbage","circle"],char:"🚯",fitzpatrick_scale:false,category:"symbols"},no_bicycles:{keywords:["cyclist","prohibited","circle"],char:"🚳",fitzpatrick_scale:false,category:"symbols"},"non-potable_water":{keywords:["drink","faucet","tap","circle"],char:"🚱",fitzpatrick_scale:false,category:"symbols"},underage:{keywords:["18","drink","pub","night","minor","circle"],char:"🔞",fitzpatrick_scale:false,category:"symbols"},no_mobile_phones:{keywords:["iphone","mute","circle"],char:"📵",fitzpatrick_scale:false,category:"symbols"},exclamation:{keywords:["heavy_exclamation_mark","danger","surprise","punctuation","wow","warning"],char:"❗",fitzpatrick_scale:false,category:"symbols"},grey_exclamation:{keywords:["surprise","punctuation","gray","wow","warning"],char:"❕",fitzpatrick_scale:false,category:"symbols"},question:{keywords:["doubt","confused"],char:"❓",fitzpatrick_scale:false,category:"symbols"},grey_question:{keywords:["doubts","gray","huh","confused"],char:"❔",fitzpatrick_scale:false,category:"symbols"},bangbang:{keywords:["exclamation","surprise"],char:"‼️",fitzpatrick_scale:false,category:"symbols"},interrobang:{keywords:["wat","punctuation","surprise"],char:"⁉️",fitzpatrick_scale:false,category:"symbols"},100:{keywords:["score","perfect","numbers","century","exam","quiz","test","pass","hundred"],char:"💯",fitzpatrick_scale:false,category:"symbols"},low_brightness:{keywords:["sun","afternoon","warm","summer"],char:"🔅",fitzpatrick_scale:false,category:"symbols"},high_brightness:{keywords:["sun","light"],char:"🔆",fitzpatrick_scale:false,category:"symbols"},trident:{keywords:["weapon","spear"],char:"🔱",fitzpatrick_scale:false,category:"symbols"},fleur_de_lis:{keywords:["decorative","scout"],char:"⚜",fitzpatrick_scale:false,category:"symbols"},part_alternation_mark:{keywords:["graph","presentation","stats","business","economics","bad"],char:"〽️",fitzpatrick_scale:false,category:"symbols"},warning:{keywords:["exclamation","wip","alert","error","problem","issue"],char:"⚠️",fitzpatrick_scale:false,category:"symbols"},children_crossing:{keywords:["school","warning","danger","sign","driving","yellow-diamond"],char:"🚸",fitzpatrick_scale:false,category:"symbols"},beginner:{keywords:["badge","shield"],char:"🔰",fitzpatrick_scale:false,category:"symbols"},recycle:{keywords:["arrow","environment","garbage","trash"],char:"♻️",fitzpatrick_scale:false,category:"symbols"},u6307:{keywords:["chinese","point","green-square","kanji"],char:"🈯",fitzpatrick_scale:false,category:"symbols"},chart:{keywords:["green-square","graph","presentation","stats"],char:"💹",fitzpatrick_scale:false,category:"symbols"},sparkle:{keywords:["stars","green-square","awesome","good","fireworks"],char:"❇️",fitzpatrick_scale:false,category:"symbols"},eight_spoked_asterisk:{keywords:["star","sparkle","green-square"],char:"✳️",fitzpatrick_scale:false,category:"symbols"},negative_squared_cross_mark:{keywords:["x","green-square","no","deny"],char:"❎",fitzpatrick_scale:false,category:"symbols"},white_check_mark:{keywords:["green-square","ok","agree","vote","election","answer","tick"],char:"✅",fitzpatrick_scale:false,category:"symbols"},diamond_shape_with_a_dot_inside:{keywords:["jewel","blue","gem","crystal","fancy"],char:"💠",fitzpatrick_scale:false,category:"symbols"},cyclone:{keywords:["weather","swirl","blue","cloud","vortex","spiral","whirlpool","spin","tornado","hurricane","typhoon"],char:"🌀",fitzpatrick_scale:false,category:"symbols"},loop:{keywords:["tape","cassette"],char:"➿",fitzpatrick_scale:false,category:"symbols"},globe_with_meridians:{keywords:["earth","international","world","internet","interweb","i18n"],char:"🌐",fitzpatrick_scale:false,category:"symbols"},m:{keywords:["alphabet","blue-circle","letter"],char:"Ⓜ️",fitzpatrick_scale:false,category:"symbols"},atm:{keywords:["money","sales","cash","blue-square","payment","bank"],char:"🏧",fitzpatrick_scale:false,category:"symbols"},sa:{keywords:["japanese","blue-square","katakana"],char:"🈂️",fitzpatrick_scale:false,category:"symbols"},passport_control:{keywords:["custom","blue-square"],char:"🛂",fitzpatrick_scale:false,category:"symbols"},customs:{keywords:["passport","border","blue-square"],char:"🛃",fitzpatrick_scale:false,category:"symbols"},baggage_claim:{keywords:["blue-square","airport","transport"],char:"🛄",fitzpatrick_scale:false,category:"symbols"},left_luggage:{keywords:["blue-square","travel"],char:"🛅",fitzpatrick_scale:false,category:"symbols"},wheelchair:{keywords:["blue-square","disabled","a11y","accessibility"],char:"♿",fitzpatrick_scale:false,category:"symbols"},no_smoking:{keywords:["cigarette","blue-square","smell","smoke"],char:"🚭",fitzpatrick_scale:false,category:"symbols"},wc:{keywords:["toilet","restroom","blue-square"],char:"🚾",fitzpatrick_scale:false,category:"symbols"},parking:{keywords:["cars","blue-square","alphabet","letter"],char:"🅿️",fitzpatrick_scale:false,category:"symbols"},potable_water:{keywords:["blue-square","liquid","restroom","cleaning","faucet"],char:"🚰",fitzpatrick_scale:false,category:"symbols"},mens:{keywords:["toilet","restroom","wc","blue-square","gender","male"],char:"🚹",fitzpatrick_scale:false,category:"symbols"},womens:{keywords:["purple-square","woman","female","toilet","loo","restroom","gender"],char:"🚺",fitzpatrick_scale:false,category:"symbols"},baby_symbol:{keywords:["orange-square","child"],char:"🚼",fitzpatrick_scale:false,category:"symbols"},restroom:{keywords:["blue-square","toilet","refresh","wc","gender"],char:"🚻",fitzpatrick_scale:false,category:"symbols"},put_litter_in_its_place:{keywords:["blue-square","sign","human","info"],char:"🚮",fitzpatrick_scale:false,category:"symbols"},cinema:{keywords:["blue-square","record","film","movie","curtain","stage","theater"],char:"🎦",fitzpatrick_scale:false,category:"symbols"},signal_strength:{keywords:["blue-square","reception","phone","internet","connection","wifi","bluetooth","bars"],char:"📶",fitzpatrick_scale:false,category:"symbols"},koko:{keywords:["blue-square","here","katakana","japanese","destination"],char:"🈁",fitzpatrick_scale:false,category:"symbols"},ng:{keywords:["blue-square","words","shape","icon"],char:"🆖",fitzpatrick_scale:false,category:"symbols"},ok:{keywords:["good","agree","yes","blue-square"],char:"🆗",fitzpatrick_scale:false,category:"symbols"},up:{keywords:["blue-square","above","high"],char:"🆙",fitzpatrick_scale:false,category:"symbols"},cool:{keywords:["words","blue-square"],char:"🆒",fitzpatrick_scale:false,category:"symbols"},new:{keywords:["blue-square","words","start"],char:"🆕",fitzpatrick_scale:false,category:"symbols"},free:{keywords:["blue-square","words"],char:"🆓",fitzpatrick_scale:false,category:"symbols"},zero:{keywords:["0","numbers","blue-square","null"],char:"0️⃣",fitzpatrick_scale:false,category:"symbols"},one:{keywords:["blue-square","numbers","1"],char:"1️⃣",fitzpatrick_scale:false,category:"symbols"},two:{keywords:["numbers","2","prime","blue-square"],char:"2️⃣",fitzpatrick_scale:false,category:"symbols"},three:{keywords:["3","numbers","prime","blue-square"],char:"3️⃣",fitzpatrick_scale:false,category:"symbols"},four:{keywords:["4","numbers","blue-square"],char:"4️⃣",fitzpatrick_scale:false,category:"symbols"},five:{keywords:["5","numbers","blue-square","prime"],char:"5️⃣",fitzpatrick_scale:false,category:"symbols"},six:{keywords:["6","numbers","blue-square"],char:"6️⃣",fitzpatrick_scale:false,category:"symbols"},seven:{keywords:["7","numbers","blue-square","prime"],char:"7️⃣",fitzpatrick_scale:false,category:"symbols"},eight:{keywords:["8","blue-square","numbers"],char:"8️⃣",fitzpatrick_scale:false,category:"symbols"},nine:{keywords:["blue-square","numbers","9"],char:"9️⃣",fitzpatrick_scale:false,category:"symbols"},keycap_ten:{keywords:["numbers","10","blue-square"],char:"🔟",fitzpatrick_scale:false,category:"symbols"},asterisk:{keywords:["star","keycap"],char:"*⃣",fitzpatrick_scale:false,category:"symbols"},1234:{keywords:["numbers","blue-square"],char:"🔢",fitzpatrick_scale:false,category:"symbols"},eject_button:{keywords:["blue-square"],char:"⏏️",fitzpatrick_scale:false,category:"symbols"},arrow_forward:{keywords:["blue-square","right","direction","play"],char:"▶️",fitzpatrick_scale:false,category:"symbols"},pause_button:{keywords:["pause","blue-square"],char:"⏸",fitzpatrick_scale:false,category:"symbols"},next_track_button:{keywords:["forward","next","blue-square"],char:"⏭",fitzpatrick_scale:false,category:"symbols"},stop_button:{keywords:["blue-square"],char:"⏹",fitzpatrick_scale:false,category:"symbols"},record_button:{keywords:["blue-square"],char:"⏺",fitzpatrick_scale:false,category:"symbols"},play_or_pause_button:{keywords:["blue-square","play","pause"],char:"⏯",fitzpatrick_scale:false,category:"symbols"},previous_track_button:{keywords:["backward"],char:"⏮",fitzpatrick_scale:false,category:"symbols"},fast_forward:{keywords:["blue-square","play","speed","continue"],char:"⏩",fitzpatrick_scale:false,category:"symbols"},rewind:{keywords:["play","blue-square"],char:"⏪",fitzpatrick_scale:false,category:"symbols"},twisted_rightwards_arrows:{keywords:["blue-square","shuffle","music","random"],char:"🔀",fitzpatrick_scale:false,category:"symbols"},repeat:{keywords:["loop","record"],char:"🔁",fitzpatrick_scale:false,category:"symbols"},repeat_one:{keywords:["blue-square","loop"],char:"🔂",fitzpatrick_scale:false,category:"symbols"},arrow_backward:{keywords:["blue-square","left","direction"],char:"◀️",fitzpatrick_scale:false,category:"symbols"},arrow_up_small:{keywords:["blue-square","triangle","direction","point","forward","top"],char:"🔼",fitzpatrick_scale:false,category:"symbols"},arrow_down_small:{keywords:["blue-square","direction","bottom"],char:"🔽",fitzpatrick_scale:false,category:"symbols"},arrow_double_up:{keywords:["blue-square","direction","top"],char:"⏫",fitzpatrick_scale:false,category:"symbols"},arrow_double_down:{keywords:["blue-square","direction","bottom"],char:"⏬",fitzpatrick_scale:false,category:"symbols"},arrow_right:{keywords:["blue-square","next"],char:"➡️",fitzpatrick_scale:false,category:"symbols"},arrow_left:{keywords:["blue-square","previous","back"],char:"⬅️",fitzpatrick_scale:false,category:"symbols"},arrow_up:{keywords:["blue-square","continue","top","direction"],char:"⬆️",fitzpatrick_scale:false,category:"symbols"},arrow_down:{keywords:["blue-square","direction","bottom"],char:"⬇️",fitzpatrick_scale:false,category:"symbols"},arrow_upper_right:{keywords:["blue-square","point","direction","diagonal","northeast"],char:"↗️",fitzpatrick_scale:false,category:"symbols"},arrow_lower_right:{keywords:["blue-square","direction","diagonal","southeast"],char:"↘️",fitzpatrick_scale:false,category:"symbols"},arrow_lower_left:{keywords:["blue-square","direction","diagonal","southwest"],char:"↙️",fitzpatrick_scale:false,category:"symbols"},arrow_upper_left:{keywords:["blue-square","point","direction","diagonal","northwest"],char:"↖️",fitzpatrick_scale:false,category:"symbols"},arrow_up_down:{keywords:["blue-square","direction","way","vertical"],char:"↕️",fitzpatrick_scale:false,category:"symbols"},left_right_arrow:{keywords:["shape","direction","horizontal","sideways"],char:"↔️",fitzpatrick_scale:false,category:"symbols"},arrows_counterclockwise:{keywords:["blue-square","sync","cycle"],char:"🔄",fitzpatrick_scale:false,category:"symbols"},arrow_right_hook:{keywords:["blue-square","return","rotate","direction"],char:"↪️",fitzpatrick_scale:false,category:"symbols"},leftwards_arrow_with_hook:{keywords:["back","return","blue-square","undo","enter"],char:"↩️",fitzpatrick_scale:false,category:"symbols"},arrow_heading_up:{keywords:["blue-square","direction","top"],char:"⤴️",fitzpatrick_scale:false,category:"symbols"},arrow_heading_down:{keywords:["blue-square","direction","bottom"],char:"⤵️",fitzpatrick_scale:false,category:"symbols"},hash:{keywords:["symbol","blue-square","twitter"],char:"#️⃣",fitzpatrick_scale:false,category:"symbols"},information_source:{keywords:["blue-square","alphabet","letter"],char:"ℹ️",fitzpatrick_scale:false,category:"symbols"},abc:{keywords:["blue-square","alphabet"],char:"🔤",fitzpatrick_scale:false,category:"symbols"},abcd:{keywords:["blue-square","alphabet"],char:"🔡",fitzpatrick_scale:false,category:"symbols"},capital_abcd:{keywords:["alphabet","words","blue-square"],char:"🔠",fitzpatrick_scale:false,category:"symbols"},symbols:{keywords:["blue-square","music","note","ampersand","percent","glyphs","characters"],char:"🔣",fitzpatrick_scale:false,category:"symbols"},musical_note:{keywords:["score","tone","sound"],char:"🎵",fitzpatrick_scale:false,category:"symbols"},notes:{keywords:["music","score"],char:"🎶",fitzpatrick_scale:false,category:"symbols"},wavy_dash:{keywords:["draw","line","moustache","mustache","squiggle","scribble"],char:"〰️",fitzpatrick_scale:false,category:"symbols"},curly_loop:{keywords:["scribble","draw","shape","squiggle"],char:"➰",fitzpatrick_scale:false,category:"symbols"},heavy_check_mark:{keywords:["ok","nike","answer","yes","tick"],char:"✔️",fitzpatrick_scale:false,category:"symbols"},arrows_clockwise:{keywords:["sync","cycle","round","repeat"],char:"🔃",fitzpatrick_scale:false,category:"symbols"},heavy_plus_sign:{keywords:["math","calculation","addition","more","increase"],char:"➕",fitzpatrick_scale:false,category:"symbols"},heavy_minus_sign:{keywords:["math","calculation","subtract","less"],char:"➖",fitzpatrick_scale:false,category:"symbols"},heavy_division_sign:{keywords:["divide","math","calculation"],char:"➗",fitzpatrick_scale:false,category:"symbols"},heavy_multiplication_x:{keywords:["math","calculation"],char:"✖️",fitzpatrick_scale:false,category:"symbols"},infinity:{keywords:["forever"],char:"♾",fitzpatrick_scale:false,category:"symbols"},heavy_dollar_sign:{keywords:["money","sales","payment","currency","buck"],char:"💲",fitzpatrick_scale:false,category:"symbols"},currency_exchange:{keywords:["money","sales","dollar","travel"],char:"💱",fitzpatrick_scale:false,category:"symbols"},copyright:{keywords:["ip","license","circle","law","legal"],char:"©️",fitzpatrick_scale:false,category:"symbols"},registered:{keywords:["alphabet","circle"],char:"®️",fitzpatrick_scale:false,category:"symbols"},tm:{keywords:["trademark","brand","law","legal"],char:"™️",fitzpatrick_scale:false,category:"symbols"},end:{keywords:["words","arrow"],char:"🔚",fitzpatrick_scale:false,category:"symbols"},back:{keywords:["arrow","words","return"],char:"🔙",fitzpatrick_scale:false,category:"symbols"},on:{keywords:["arrow","words"],char:"🔛",fitzpatrick_scale:false,category:"symbols"},top:{keywords:["words","blue-square"],char:"🔝",fitzpatrick_scale:false,category:"symbols"},soon:{keywords:["arrow","words"],char:"🔜",fitzpatrick_scale:false,category:"symbols"},ballot_box_with_check:{keywords:["ok","agree","confirm","black-square","vote","election","yes","tick"],char:"☑️",fitzpatrick_scale:false,category:"symbols"},radio_button:{keywords:["input","old","music","circle"],char:"🔘",fitzpatrick_scale:false,category:"symbols"},white_circle:{keywords:["shape","round"],char:"⚪",fitzpatrick_scale:false,category:"symbols"},black_circle:{keywords:["shape","button","round"],char:"⚫",fitzpatrick_scale:false,category:"symbols"},red_circle:{keywords:["shape","error","danger"],char:"🔴",fitzpatrick_scale:false,category:"symbols"},large_blue_circle:{keywords:["shape","icon","button"],char:"🔵",fitzpatrick_scale:false,category:"symbols"},small_orange_diamond:{keywords:["shape","jewel","gem"],char:"🔸",fitzpatrick_scale:false,category:"symbols"},small_blue_diamond:{keywords:["shape","jewel","gem"],char:"🔹",fitzpatrick_scale:false,category:"symbols"},large_orange_diamond:{keywords:["shape","jewel","gem"],char:"🔶",fitzpatrick_scale:false,category:"symbols"},large_blue_diamond:{keywords:["shape","jewel","gem"],char:"🔷",fitzpatrick_scale:false,category:"symbols"},small_red_triangle:{keywords:["shape","direction","up","top"],char:"🔺",fitzpatrick_scale:false,category:"symbols"},black_small_square:{keywords:["shape","icon"],char:"▪️",fitzpatrick_scale:false,category:"symbols"},white_small_square:{keywords:["shape","icon"],char:"▫️",fitzpatrick_scale:false,category:"symbols"},black_large_square:{keywords:["shape","icon","button"],char:"⬛",fitzpatrick_scale:false,category:"symbols"},white_large_square:{keywords:["shape","icon","stone","button"],char:"⬜",fitzpatrick_scale:false,category:"symbols"},small_red_triangle_down:{keywords:["shape","direction","bottom"],char:"🔻",fitzpatrick_scale:false,category:"symbols"},black_medium_square:{keywords:["shape","button","icon"],char:"◼️",fitzpatrick_scale:false,category:"symbols"},white_medium_square:{keywords:["shape","stone","icon"],char:"◻️",fitzpatrick_scale:false,category:"symbols"},black_medium_small_square:{keywords:["icon","shape","button"],char:"◾",fitzpatrick_scale:false,category:"symbols"},white_medium_small_square:{keywords:["shape","stone","icon","button"],char:"◽",fitzpatrick_scale:false,category:"symbols"},black_square_button:{keywords:["shape","input","frame"],char:"🔲",fitzpatrick_scale:false,category:"symbols"},white_square_button:{keywords:["shape","input"],char:"🔳",fitzpatrick_scale:false,category:"symbols"},speaker:{keywords:["sound","volume","silence","broadcast"],char:"🔈",fitzpatrick_scale:false,category:"symbols"},sound:{keywords:["volume","speaker","broadcast"],char:"🔉",fitzpatrick_scale:false,category:"symbols"},loud_sound:{keywords:["volume","noise","noisy","speaker","broadcast"],char:"🔊",fitzpatrick_scale:false,category:"symbols"},mute:{keywords:["sound","volume","silence","quiet"],char:"🔇",fitzpatrick_scale:false,category:"symbols"},mega:{keywords:["sound","speaker","volume"],char:"📣",fitzpatrick_scale:false,category:"symbols"},loudspeaker:{keywords:["volume","sound"],char:"📢",fitzpatrick_scale:false,category:"symbols"},bell:{keywords:["sound","notification","christmas","xmas","chime"],char:"🔔",fitzpatrick_scale:false,category:"symbols"},no_bell:{keywords:["sound","volume","mute","quiet","silent"],char:"🔕",fitzpatrick_scale:false,category:"symbols"},black_joker:{keywords:["poker","cards","game","play","magic"],char:"🃏",fitzpatrick_scale:false,category:"symbols"},mahjong:{keywords:["game","play","chinese","kanji"],char:"🀄",fitzpatrick_scale:false,category:"symbols"},spades:{keywords:["poker","cards","suits","magic"],char:"♠️",fitzpatrick_scale:false,category:"symbols"},clubs:{keywords:["poker","cards","magic","suits"],char:"♣️",fitzpatrick_scale:false,category:"symbols"},hearts:{keywords:["poker","cards","magic","suits"],char:"♥️",fitzpatrick_scale:false,category:"symbols"},diamonds:{keywords:["poker","cards","magic","suits"],char:"♦️",fitzpatrick_scale:false,category:"symbols"},flower_playing_cards:{keywords:["game","sunset","red"],char:"🎴",fitzpatrick_scale:false,category:"symbols"},thought_balloon:{keywords:["bubble","cloud","speech","thinking","dream"],char:"💭",fitzpatrick_scale:false,category:"symbols"},right_anger_bubble:{keywords:["caption","speech","thinking","mad"],char:"🗯",fitzpatrick_scale:false,category:"symbols"},speech_balloon:{keywords:["bubble","words","message","talk","chatting"],char:"💬",fitzpatrick_scale:false,category:"symbols"},left_speech_bubble:{keywords:["words","message","talk","chatting"],char:"🗨",fitzpatrick_scale:false,category:"symbols"},clock1:{keywords:["time","late","early","schedule"],char:"🕐",fitzpatrick_scale:false,category:"symbols"},clock2:{keywords:["time","late","early","schedule"],char:"🕑",fitzpatrick_scale:false,category:"symbols"},clock3:{keywords:["time","late","early","schedule"],char:"🕒",fitzpatrick_scale:false,category:"symbols"},clock4:{keywords:["time","late","early","schedule"],char:"🕓",fitzpatrick_scale:false,category:"symbols"},clock5:{keywords:["time","late","early","schedule"],char:"🕔",fitzpatrick_scale:false,category:"symbols"},clock6:{keywords:["time","late","early","schedule","dawn","dusk"],char:"🕕",fitzpatrick_scale:false,category:"symbols"},clock7:{keywords:["time","late","early","schedule"],char:"🕖",fitzpatrick_scale:false,category:"symbols"},clock8:{keywords:["time","late","early","schedule"],char:"🕗",fitzpatrick_scale:false,category:"symbols"},clock9:{keywords:["time","late","early","schedule"],char:"🕘",fitzpatrick_scale:false,category:"symbols"},clock10:{keywords:["time","late","early","schedule"],char:"🕙",fitzpatrick_scale:false,category:"symbols"},clock11:{keywords:["time","late","early","schedule"],char:"🕚",fitzpatrick_scale:false,category:"symbols"},clock12:{keywords:["time","noon","midnight","midday","late","early","schedule"],char:"🕛",fitzpatrick_scale:false,category:"symbols"},clock130:{keywords:["time","late","early","schedule"],char:"🕜",fitzpatrick_scale:false,category:"symbols"},clock230:{keywords:["time","late","early","schedule"],char:"🕝",fitzpatrick_scale:false,category:"symbols"},clock330:{keywords:["time","late","early","schedule"],char:"🕞",fitzpatrick_scale:false,category:"symbols"},clock430:{keywords:["time","late","early","schedule"],char:"🕟",fitzpatrick_scale:false,category:"symbols"},clock530:{keywords:["time","late","early","schedule"],char:"🕠",fitzpatrick_scale:false,category:"symbols"},clock630:{keywords:["time","late","early","schedule"],char:"🕡",fitzpatrick_scale:false,category:"symbols"},clock730:{keywords:["time","late","early","schedule"],char:"🕢",fitzpatrick_scale:false,category:"symbols"},clock830:{keywords:["time","late","early","schedule"],char:"🕣",fitzpatrick_scale:false,category:"symbols"},clock930:{keywords:["time","late","early","schedule"],char:"🕤",fitzpatrick_scale:false,category:"symbols"},clock1030:{keywords:["time","late","early","schedule"],char:"🕥",fitzpatrick_scale:false,category:"symbols"},clock1130:{keywords:["time","late","early","schedule"],char:"🕦",fitzpatrick_scale:false,category:"symbols"},clock1230:{keywords:["time","late","early","schedule"],char:"🕧",fitzpatrick_scale:false,category:"symbols"},afghanistan:{keywords:["af","flag","nation","country","banner"],char:"🇦🇫",fitzpatrick_scale:false,category:"flags"},aland_islands:{keywords:["Åland","islands","flag","nation","country","banner"],char:"🇦🇽",fitzpatrick_scale:false,category:"flags"},albania:{keywords:["al","flag","nation","country","banner"],char:"🇦🇱",fitzpatrick_scale:false,category:"flags"},algeria:{keywords:["dz","flag","nation","country","banner"],char:"🇩🇿",fitzpatrick_scale:false,category:"flags"},american_samoa:{keywords:["american","ws","flag","nation","country","banner"],char:"🇦🇸",fitzpatrick_scale:false,category:"flags"},andorra:{keywords:["ad","flag","nation","country","banner"],char:"🇦🇩",fitzpatrick_scale:false,category:"flags"},angola:{keywords:["ao","flag","nation","country","banner"],char:"🇦🇴",fitzpatrick_scale:false,category:"flags"},anguilla:{keywords:["ai","flag","nation","country","banner"],char:"🇦🇮",fitzpatrick_scale:false,category:"flags"},antarctica:{keywords:["aq","flag","nation","country","banner"],char:"🇦🇶",fitzpatrick_scale:false,category:"flags"},antigua_barbuda:{keywords:["antigua","barbuda","flag","nation","country","banner"],char:"🇦🇬",fitzpatrick_scale:false,category:"flags"},argentina:{keywords:["ar","flag","nation","country","banner"],char:"🇦🇷",fitzpatrick_scale:false,category:"flags"},armenia:{keywords:["am","flag","nation","country","banner"],char:"🇦🇲",fitzpatrick_scale:false,category:"flags"},aruba:{keywords:["aw","flag","nation","country","banner"],char:"🇦🇼",fitzpatrick_scale:false,category:"flags"},australia:{keywords:["au","flag","nation","country","banner"],char:"🇦🇺",fitzpatrick_scale:false,category:"flags"},austria:{keywords:["at","flag","nation","country","banner"],char:"🇦🇹",fitzpatrick_scale:false,category:"flags"},azerbaijan:{keywords:["az","flag","nation","country","banner"],char:"🇦🇿",fitzpatrick_scale:false,category:"flags"},bahamas:{keywords:["bs","flag","nation","country","banner"],char:"🇧🇸",fitzpatrick_scale:false,category:"flags"},bahrain:{keywords:["bh","flag","nation","country","banner"],char:"🇧🇭",fitzpatrick_scale:false,category:"flags"},bangladesh:{keywords:["bd","flag","nation","country","banner"],char:"🇧🇩",fitzpatrick_scale:false,category:"flags"},barbados:{keywords:["bb","flag","nation","country","banner"],char:"🇧🇧",fitzpatrick_scale:false,category:"flags"},belarus:{keywords:["by","flag","nation","country","banner"],char:"🇧🇾",fitzpatrick_scale:false,category:"flags"},belgium:{keywords:["be","flag","nation","country","banner"],char:"🇧🇪",fitzpatrick_scale:false,category:"flags"},belize:{keywords:["bz","flag","nation","country","banner"],char:"🇧🇿",fitzpatrick_scale:false,category:"flags"},benin:{keywords:["bj","flag","nation","country","banner"],char:"🇧🇯",fitzpatrick_scale:false,category:"flags"},bermuda:{keywords:["bm","flag","nation","country","banner"],char:"🇧🇲",fitzpatrick_scale:false,category:"flags"},bhutan:{keywords:["bt","flag","nation","country","banner"],char:"🇧🇹",fitzpatrick_scale:false,category:"flags"},bolivia:{keywords:["bo","flag","nation","country","banner"],char:"🇧🇴",fitzpatrick_scale:false,category:"flags"},caribbean_netherlands:{keywords:["bonaire","flag","nation","country","banner"],char:"🇧🇶",fitzpatrick_scale:false,category:"flags"},bosnia_herzegovina:{keywords:["bosnia","herzegovina","flag","nation","country","banner"],char:"🇧🇦",fitzpatrick_scale:false,category:"flags"},botswana:{keywords:["bw","flag","nation","country","banner"],char:"🇧🇼",fitzpatrick_scale:false,category:"flags"},brazil:{keywords:["br","flag","nation","country","banner"],char:"🇧🇷",fitzpatrick_scale:false,category:"flags"},british_indian_ocean_territory:{keywords:["british","indian","ocean","territory","flag","nation","country","banner"],char:"🇮🇴",fitzpatrick_scale:false,category:"flags"},british_virgin_islands:{keywords:["british","virgin","islands","bvi","flag","nation","country","banner"],char:"🇻🇬",fitzpatrick_scale:false,category:"flags"},brunei:{keywords:["bn","darussalam","flag","nation","country","banner"],char:"🇧🇳",fitzpatrick_scale:false,category:"flags"},bulgaria:{keywords:["bg","flag","nation","country","banner"],char:"🇧🇬",fitzpatrick_scale:false,category:"flags"},burkina_faso:{keywords:["burkina","faso","flag","nation","country","banner"],char:"🇧🇫",fitzpatrick_scale:false,category:"flags"},burundi:{keywords:["bi","flag","nation","country","banner"],char:"🇧🇮",fitzpatrick_scale:false,category:"flags"},cape_verde:{keywords:["cabo","verde","flag","nation","country","banner"],char:"🇨🇻",fitzpatrick_scale:false,category:"flags"},cambodia:{keywords:["kh","flag","nation","country","banner"],char:"🇰🇭",fitzpatrick_scale:false,category:"flags"},cameroon:{keywords:["cm","flag","nation","country","banner"],char:"🇨🇲",fitzpatrick_scale:false,category:"flags"},canada:{keywords:["ca","flag","nation","country","banner"],char:"🇨🇦",fitzpatrick_scale:false,category:"flags"},canary_islands:{keywords:["canary","islands","flag","nation","country","banner"],char:"🇮🇨",fitzpatrick_scale:false,category:"flags"},cayman_islands:{keywords:["cayman","islands","flag","nation","country","banner"],char:"🇰🇾",fitzpatrick_scale:false,category:"flags"},central_african_republic:{keywords:["central","african","republic","flag","nation","country","banner"],char:"🇨🇫",fitzpatrick_scale:false,category:"flags"},chad:{keywords:["td","flag","nation","country","banner"],char:"🇹🇩",fitzpatrick_scale:false,category:"flags"},chile:{keywords:["flag","nation","country","banner"],char:"🇨🇱",fitzpatrick_scale:false,category:"flags"},cn:{keywords:["china","chinese","prc","flag","country","nation","banner"],char:"🇨🇳",fitzpatrick_scale:false,category:"flags"},christmas_island:{keywords:["christmas","island","flag","nation","country","banner"],char:"🇨🇽",fitzpatrick_scale:false,category:"flags"},cocos_islands:{keywords:["cocos","keeling","islands","flag","nation","country","banner"],char:"🇨🇨",fitzpatrick_scale:false,category:"flags"},colombia:{keywords:["co","flag","nation","country","banner"],char:"🇨🇴",fitzpatrick_scale:false,category:"flags"},comoros:{keywords:["km","flag","nation","country","banner"],char:"🇰🇲",fitzpatrick_scale:false,category:"flags"},congo_brazzaville:{keywords:["congo","flag","nation","country","banner"],char:"🇨🇬",fitzpatrick_scale:false,category:"flags"},congo_kinshasa:{keywords:["congo","democratic","republic","flag","nation","country","banner"],char:"🇨🇩",fitzpatrick_scale:false,category:"flags"},cook_islands:{keywords:["cook","islands","flag","nation","country","banner"],char:"🇨🇰",fitzpatrick_scale:false,category:"flags"},costa_rica:{keywords:["costa","rica","flag","nation","country","banner"],char:"🇨🇷",fitzpatrick_scale:false,category:"flags"},croatia:{keywords:["hr","flag","nation","country","banner"],char:"🇭🇷",fitzpatrick_scale:false,category:"flags"},cuba:{keywords:["cu","flag","nation","country","banner"],char:"🇨🇺",fitzpatrick_scale:false,category:"flags"},curacao:{keywords:["curaçao","flag","nation","country","banner"],char:"🇨🇼",fitzpatrick_scale:false,category:"flags"},cyprus:{keywords:["cy","flag","nation","country","banner"],char:"🇨🇾",fitzpatrick_scale:false,category:"flags"},czech_republic:{keywords:["cz","flag","nation","country","banner"],char:"🇨🇿",fitzpatrick_scale:false,category:"flags"},denmark:{keywords:["dk","flag","nation","country","banner"],char:"🇩🇰",fitzpatrick_scale:false,category:"flags"},djibouti:{keywords:["dj","flag","nation","country","banner"],char:"🇩🇯",fitzpatrick_scale:false,category:"flags"},dominica:{keywords:["dm","flag","nation","country","banner"],char:"🇩🇲",fitzpatrick_scale:false,category:"flags"},dominican_republic:{keywords:["dominican","republic","flag","nation","country","banner"],char:"🇩🇴",fitzpatrick_scale:false,category:"flags"},ecuador:{keywords:["ec","flag","nation","country","banner"],char:"🇪🇨",fitzpatrick_scale:false,category:"flags"},egypt:{keywords:["eg","flag","nation","country","banner"],char:"🇪🇬",fitzpatrick_scale:false,category:"flags"},el_salvador:{keywords:["el","salvador","flag","nation","country","banner"],char:"🇸🇻",fitzpatrick_scale:false,category:"flags"},equatorial_guinea:{keywords:["equatorial","gn","flag","nation","country","banner"],char:"🇬🇶",fitzpatrick_scale:false,category:"flags"},eritrea:{keywords:["er","flag","nation","country","banner"],char:"🇪🇷",fitzpatrick_scale:false,category:"flags"},estonia:{keywords:["ee","flag","nation","country","banner"],char:"🇪🇪",fitzpatrick_scale:false,category:"flags"},ethiopia:{keywords:["et","flag","nation","country","banner"],char:"🇪🇹",fitzpatrick_scale:false,category:"flags"},eu:{keywords:["european","union","flag","banner"],char:"🇪🇺",fitzpatrick_scale:false,category:"flags"},falkland_islands:{keywords:["falkland","islands","malvinas","flag","nation","country","banner"],char:"🇫🇰",fitzpatrick_scale:false,category:"flags"},faroe_islands:{keywords:["faroe","islands","flag","nation","country","banner"],char:"🇫🇴",fitzpatrick_scale:false,category:"flags"},fiji:{keywords:["fj","flag","nation","country","banner"],char:"🇫🇯",fitzpatrick_scale:false,category:"flags"},finland:{keywords:["fi","flag","nation","country","banner"],char:"🇫🇮",fitzpatrick_scale:false,category:"flags"},fr:{keywords:["banner","flag","nation","france","french","country"],char:"🇫🇷",fitzpatrick_scale:false,category:"flags"},french_guiana:{keywords:["french","guiana","flag","nation","country","banner"],char:"🇬🇫",fitzpatrick_scale:false,category:"flags"},french_polynesia:{keywords:["french","polynesia","flag","nation","country","banner"],char:"🇵🇫",fitzpatrick_scale:false,category:"flags"},french_southern_territories:{keywords:["french","southern","territories","flag","nation","country","banner"],char:"🇹🇫",fitzpatrick_scale:false,category:"flags"},gabon:{keywords:["ga","flag","nation","country","banner"],char:"🇬🇦",fitzpatrick_scale:false,category:"flags"},gambia:{keywords:["gm","flag","nation","country","banner"],char:"🇬🇲",fitzpatrick_scale:false,category:"flags"},georgia:{keywords:["ge","flag","nation","country","banner"],char:"🇬🇪",fitzpatrick_scale:false,category:"flags"},de:{keywords:["german","nation","flag","country","banner"],char:"🇩🇪",fitzpatrick_scale:false,category:"flags"},ghana:{keywords:["gh","flag","nation","country","banner"],char:"🇬🇭",fitzpatrick_scale:false,category:"flags"},gibraltar:{keywords:["gi","flag","nation","country","banner"],char:"🇬🇮",fitzpatrick_scale:false,category:"flags"},greece:{keywords:["gr","flag","nation","country","banner"],char:"🇬🇷",fitzpatrick_scale:false,category:"flags"},greenland:{keywords:["gl","flag","nation","country","banner"],char:"🇬🇱",fitzpatrick_scale:false,category:"flags"},grenada:{keywords:["gd","flag","nation","country","banner"],char:"🇬🇩",fitzpatrick_scale:false,category:"flags"},guadeloupe:{keywords:["gp","flag","nation","country","banner"],char:"🇬🇵",fitzpatrick_scale:false,category:"flags"},guam:{keywords:["gu","flag","nation","country","banner"],char:"🇬🇺",fitzpatrick_scale:false,category:"flags"},guatemala:{keywords:["gt","flag","nation","country","banner"],char:"🇬🇹",fitzpatrick_scale:false,category:"flags"},guernsey:{keywords:["gg","flag","nation","country","banner"],char:"🇬🇬",fitzpatrick_scale:false,category:"flags"},guinea:{keywords:["gn","flag","nation","country","banner"],char:"🇬🇳",fitzpatrick_scale:false,category:"flags"},guinea_bissau:{keywords:["gw","bissau","flag","nation","country","banner"],char:"🇬🇼",fitzpatrick_scale:false,category:"flags"},guyana:{keywords:["gy","flag","nation","country","banner"],char:"🇬🇾",fitzpatrick_scale:false,category:"flags"},haiti:{keywords:["ht","flag","nation","country","banner"],char:"🇭🇹",fitzpatrick_scale:false,category:"flags"},honduras:{keywords:["hn","flag","nation","country","banner"],char:"🇭🇳",fitzpatrick_scale:false,category:"flags"},hong_kong:{keywords:["hong","kong","flag","nation","country","banner"],char:"🇭🇰",fitzpatrick_scale:false,category:"flags"},hungary:{keywords:["hu","flag","nation","country","banner"],char:"🇭🇺",fitzpatrick_scale:false,category:"flags"},iceland:{keywords:["is","flag","nation","country","banner"],char:"🇮🇸",fitzpatrick_scale:false,category:"flags"},india:{keywords:["in","flag","nation","country","banner"],char:"🇮🇳",fitzpatrick_scale:false,category:"flags"},indonesia:{keywords:["flag","nation","country","banner"],char:"🇮🇩",fitzpatrick_scale:false,category:"flags"},iran:{keywords:["iran,","islamic","republic","flag","nation","country","banner"],char:"🇮🇷",fitzpatrick_scale:false,category:"flags"},iraq:{keywords:["iq","flag","nation","country","banner"],char:"🇮🇶",fitzpatrick_scale:false,category:"flags"},ireland:{keywords:["ie","flag","nation","country","banner"],char:"🇮🇪",fitzpatrick_scale:false,category:"flags"},isle_of_man:{keywords:["isle","man","flag","nation","country","banner"],char:"🇮🇲",fitzpatrick_scale:false,category:"flags"},israel:{keywords:["il","flag","nation","country","banner"],char:"🇮🇱",fitzpatrick_scale:false,category:"flags"},it:{keywords:["italy","flag","nation","country","banner"],char:"🇮🇹",fitzpatrick_scale:false,category:"flags"},cote_divoire:{keywords:["ivory","coast","flag","nation","country","banner"],char:"🇨🇮",fitzpatrick_scale:false,category:"flags"},jamaica:{keywords:["jm","flag","nation","country","banner"],char:"🇯🇲",fitzpatrick_scale:false,category:"flags"},jp:{keywords:["japanese","nation","flag","country","banner"],char:"🇯🇵",fitzpatrick_scale:false,category:"flags"},jersey:{keywords:["je","flag","nation","country","banner"],char:"🇯🇪",fitzpatrick_scale:false,category:"flags"},jordan:{keywords:["jo","flag","nation","country","banner"],char:"🇯🇴",fitzpatrick_scale:false,category:"flags"},kazakhstan:{keywords:["kz","flag","nation","country","banner"],char:"🇰🇿",fitzpatrick_scale:false,category:"flags"},kenya:{keywords:["ke","flag","nation","country","banner"],char:"🇰🇪",fitzpatrick_scale:false,category:"flags"},kiribati:{keywords:["ki","flag","nation","country","banner"],char:"🇰🇮",fitzpatrick_scale:false,category:"flags"},kosovo:{keywords:["xk","flag","nation","country","banner"],char:"🇽🇰",fitzpatrick_scale:false,category:"flags"},kuwait:{keywords:["kw","flag","nation","country","banner"],char:"🇰🇼",fitzpatrick_scale:false,category:"flags"},kyrgyzstan:{keywords:["kg","flag","nation","country","banner"],char:"🇰🇬",fitzpatrick_scale:false,category:"flags"},laos:{keywords:["lao","democratic","republic","flag","nation","country","banner"],char:"🇱🇦",fitzpatrick_scale:false,category:"flags"},latvia:{keywords:["lv","flag","nation","country","banner"],char:"🇱🇻",fitzpatrick_scale:false,category:"flags"},lebanon:{keywords:["lb","flag","nation","country","banner"],char:"🇱🇧",fitzpatrick_scale:false,category:"flags"},lesotho:{keywords:["ls","flag","nation","country","banner"],char:"🇱🇸",fitzpatrick_scale:false,category:"flags"},liberia:{keywords:["lr","flag","nation","country","banner"],char:"🇱🇷",fitzpatrick_scale:false,category:"flags"},libya:{keywords:["ly","flag","nation","country","banner"],char:"🇱🇾",fitzpatrick_scale:false,category:"flags"},liechtenstein:{keywords:["li","flag","nation","country","banner"],char:"🇱🇮",fitzpatrick_scale:false,category:"flags"},lithuania:{keywords:["lt","flag","nation","country","banner"],char:"🇱🇹",fitzpatrick_scale:false,category:"flags"},luxembourg:{keywords:["lu","flag","nation","country","banner"],char:"🇱🇺",fitzpatrick_scale:false,category:"flags"},macau:{keywords:["macao","flag","nation","country","banner"],char:"🇲🇴",fitzpatrick_scale:false,category:"flags"},macedonia:{keywords:["macedonia,","flag","nation","country","banner"],char:"🇲🇰",fitzpatrick_scale:false,category:"flags"},madagascar:{keywords:["mg","flag","nation","country","banner"],char:"🇲🇬",fitzpatrick_scale:false,category:"flags"},malawi:{keywords:["mw","flag","nation","country","banner"],char:"🇲🇼",fitzpatrick_scale:false,category:"flags"},malaysia:{keywords:["my","flag","nation","country","banner"],char:"🇲🇾",fitzpatrick_scale:false,category:"flags"},maldives:{keywords:["mv","flag","nation","country","banner"],char:"🇲🇻",fitzpatrick_scale:false,category:"flags"},mali:{keywords:["ml","flag","nation","country","banner"],char:"🇲🇱",fitzpatrick_scale:false,category:"flags"},malta:{keywords:["mt","flag","nation","country","banner"],char:"🇲🇹",fitzpatrick_scale:false,category:"flags"},marshall_islands:{keywords:["marshall","islands","flag","nation","country","banner"],char:"🇲🇭",fitzpatrick_scale:false,category:"flags"},martinique:{keywords:["mq","flag","nation","country","banner"],char:"🇲🇶",fitzpatrick_scale:false,category:"flags"},mauritania:{keywords:["mr","flag","nation","country","banner"],char:"🇲🇷",fitzpatrick_scale:false,category:"flags"},mauritius:{keywords:["mu","flag","nation","country","banner"],char:"🇲🇺",fitzpatrick_scale:false,category:"flags"},mayotte:{keywords:["yt","flag","nation","country","banner"],char:"🇾🇹",fitzpatrick_scale:false,category:"flags"},mexico:{keywords:["mx","flag","nation","country","banner"],char:"🇲🇽",fitzpatrick_scale:false,category:"flags"},micronesia:{keywords:["micronesia,","federated","states","flag","nation","country","banner"],char:"🇫🇲",fitzpatrick_scale:false,category:"flags"},moldova:{keywords:["moldova,","republic","flag","nation","country","banner"],char:"🇲🇩",fitzpatrick_scale:false,category:"flags"},monaco:{keywords:["mc","flag","nation","country","banner"],char:"🇲🇨",fitzpatrick_scale:false,category:"flags"},mongolia:{keywords:["mn","flag","nation","country","banner"],char:"🇲🇳",fitzpatrick_scale:false,category:"flags"},montenegro:{keywords:["me","flag","nation","country","banner"],char:"🇲🇪",fitzpatrick_scale:false,category:"flags"},montserrat:{keywords:["ms","flag","nation","country","banner"],char:"🇲🇸",fitzpatrick_scale:false,category:"flags"},morocco:{keywords:["ma","flag","nation","country","banner"],char:"🇲🇦",fitzpatrick_scale:false,category:"flags"},mozambique:{keywords:["mz","flag","nation","country","banner"],char:"🇲🇿",fitzpatrick_scale:false,category:"flags"},myanmar:{keywords:["mm","flag","nation","country","banner"],char:"🇲🇲",fitzpatrick_scale:false,category:"flags"},namibia:{keywords:["na","flag","nation","country","banner"],char:"🇳🇦",fitzpatrick_scale:false,category:"flags"},nauru:{keywords:["nr","flag","nation","country","banner"],char:"🇳🇷",fitzpatrick_scale:false,category:"flags"},nepal:{keywords:["np","flag","nation","country","banner"],char:"🇳🇵",fitzpatrick_scale:false,category:"flags"},netherlands:{keywords:["nl","flag","nation","country","banner"],char:"🇳🇱",fitzpatrick_scale:false,category:"flags"},new_caledonia:{keywords:["new","caledonia","flag","nation","country","banner"],char:"🇳🇨",fitzpatrick_scale:false,category:"flags"},new_zealand:{keywords:["new","zealand","flag","nation","country","banner"],char:"🇳🇿",fitzpatrick_scale:false,category:"flags"},nicaragua:{keywords:["ni","flag","nation","country","banner"],char:"🇳🇮",fitzpatrick_scale:false,category:"flags"},niger:{keywords:["ne","flag","nation","country","banner"],char:"🇳🇪",fitzpatrick_scale:false,category:"flags"},nigeria:{keywords:["flag","nation","country","banner"],char:"🇳🇬",fitzpatrick_scale:false,category:"flags"},niue:{keywords:["nu","flag","nation","country","banner"],char:"🇳🇺",fitzpatrick_scale:false,category:"flags"},norfolk_island:{keywords:["norfolk","island","flag","nation","country","banner"],char:"🇳🇫",fitzpatrick_scale:false,category:"flags"},northern_mariana_islands:{keywords:["northern","mariana","islands","flag","nation","country","banner"],char:"🇲🇵",fitzpatrick_scale:false,category:"flags"},north_korea:{keywords:["north","korea","nation","flag","country","banner"],char:"🇰🇵",fitzpatrick_scale:false,category:"flags"},norway:{keywords:["no","flag","nation","country","banner"],char:"🇳🇴",fitzpatrick_scale:false,category:"flags"},oman:{keywords:["om_symbol","flag","nation","country","banner"],char:"🇴🇲",fitzpatrick_scale:false,category:"flags"},pakistan:{keywords:["pk","flag","nation","country","banner"],char:"🇵🇰",fitzpatrick_scale:false,category:"flags"},palau:{keywords:["pw","flag","nation","country","banner"],char:"🇵🇼",fitzpatrick_scale:false,category:"flags"},palestinian_territories:{keywords:["palestine","palestinian","territories","flag","nation","country","banner"],char:"🇵🇸",fitzpatrick_scale:false,category:"flags"},panama:{keywords:["pa","flag","nation","country","banner"],char:"🇵🇦",fitzpatrick_scale:false,category:"flags"},papua_new_guinea:{keywords:["papua","new","guinea","flag","nation","country","banner"],char:"🇵🇬",fitzpatrick_scale:false,category:"flags"},paraguay:{keywords:["py","flag","nation","country","banner"],char:"🇵🇾",fitzpatrick_scale:false,category:"flags"},peru:{keywords:["pe","flag","nation","country","banner"],char:"🇵🇪",fitzpatrick_scale:false,category:"flags"},philippines:{keywords:["ph","flag","nation","country","banner"],char:"🇵🇭",fitzpatrick_scale:false,category:"flags"},pitcairn_islands:{keywords:["pitcairn","flag","nation","country","banner"],char:"🇵🇳",fitzpatrick_scale:false,category:"flags"},poland:{keywords:["pl","flag","nation","country","banner"],char:"🇵🇱",fitzpatrick_scale:false,category:"flags"},portugal:{keywords:["pt","flag","nation","country","banner"],char:"🇵🇹",fitzpatrick_scale:false,category:"flags"},puerto_rico:{keywords:["puerto","rico","flag","nation","country","banner"],char:"🇵🇷",fitzpatrick_scale:false,category:"flags"},qatar:{keywords:["qa","flag","nation","country","banner"],char:"🇶🇦",fitzpatrick_scale:false,category:"flags"},reunion:{keywords:["réunion","flag","nation","country","banner"],char:"🇷🇪",fitzpatrick_scale:false,category:"flags"},romania:{keywords:["ro","flag","nation","country","banner"],char:"🇷🇴",fitzpatrick_scale:false,category:"flags"},ru:{keywords:["russian","federation","flag","nation","country","banner"],char:"🇷🇺",fitzpatrick_scale:false,category:"flags"},rwanda:{keywords:["rw","flag","nation","country","banner"],char:"🇷🇼",fitzpatrick_scale:false,category:"flags"},st_barthelemy:{keywords:["saint","barthélemy","flag","nation","country","banner"],char:"🇧🇱",fitzpatrick_scale:false,category:"flags"},st_helena:{keywords:["saint","helena","ascension","tristan","cunha","flag","nation","country","banner"],char:"🇸🇭",fitzpatrick_scale:false,category:"flags"},st_kitts_nevis:{keywords:["saint","kitts","nevis","flag","nation","country","banner"],char:"🇰🇳",fitzpatrick_scale:false,category:"flags"},st_lucia:{keywords:["saint","lucia","flag","nation","country","banner"],char:"🇱🇨",fitzpatrick_scale:false,category:"flags"},st_pierre_miquelon:{keywords:["saint","pierre","miquelon","flag","nation","country","banner"],char:"🇵🇲",fitzpatrick_scale:false,category:"flags"},st_vincent_grenadines:{keywords:["saint","vincent","grenadines","flag","nation","country","banner"],char:"🇻🇨",fitzpatrick_scale:false,category:"flags"},samoa:{keywords:["ws","flag","nation","country","banner"],char:"🇼🇸",fitzpatrick_scale:false,category:"flags"},san_marino:{keywords:["san","marino","flag","nation","country","banner"],char:"🇸🇲",fitzpatrick_scale:false,category:"flags"},sao_tome_principe:{keywords:["sao","tome","principe","flag","nation","country","banner"],char:"🇸🇹",fitzpatrick_scale:false,category:"flags"},saudi_arabia:{keywords:["flag","nation","country","banner"],char:"🇸🇦",fitzpatrick_scale:false,category:"flags"},senegal:{keywords:["sn","flag","nation","country","banner"],char:"🇸🇳",fitzpatrick_scale:false,category:"flags"},serbia:{keywords:["rs","flag","nation","country","banner"],char:"🇷🇸",fitzpatrick_scale:false,category:"flags"},seychelles:{keywords:["sc","flag","nation","country","banner"],char:"🇸🇨",fitzpatrick_scale:false,category:"flags"},sierra_leone:{keywords:["sierra","leone","flag","nation","country","banner"],char:"🇸🇱",fitzpatrick_scale:false,category:"flags"},singapore:{keywords:["sg","flag","nation","country","banner"],char:"🇸🇬",fitzpatrick_scale:false,category:"flags"},sint_maarten:{keywords:["sint","maarten","dutch","flag","nation","country","banner"],char:"🇸🇽",fitzpatrick_scale:false,category:"flags"},slovakia:{keywords:["sk","flag","nation","country","banner"],char:"🇸🇰",fitzpatrick_scale:false,category:"flags"},slovenia:{keywords:["si","flag","nation","country","banner"],char:"🇸🇮",fitzpatrick_scale:false,category:"flags"},solomon_islands:{keywords:["solomon","islands","flag","nation","country","banner"],char:"🇸🇧",fitzpatrick_scale:false,category:"flags"},somalia:{keywords:["so","flag","nation","country","banner"],char:"🇸🇴",fitzpatrick_scale:false,category:"flags"},south_africa:{keywords:["south","africa","flag","nation","country","banner"],char:"🇿🇦",fitzpatrick_scale:false,category:"flags"},south_georgia_south_sandwich_islands:{keywords:["south","georgia","sandwich","islands","flag","nation","country","banner"],char:"🇬🇸",fitzpatrick_scale:false,category:"flags"},kr:{keywords:["south","korea","nation","flag","country","banner"],char:"🇰🇷",fitzpatrick_scale:false,category:"flags"},south_sudan:{keywords:["south","sd","flag","nation","country","banner"],char:"🇸🇸",fitzpatrick_scale:false,category:"flags"},es:{keywords:["spain","flag","nation","country","banner"],char:"🇪🇸",fitzpatrick_scale:false,category:"flags"},sri_lanka:{keywords:["sri","lanka","flag","nation","country","banner"],char:"🇱🇰",fitzpatrick_scale:false,category:"flags"},sudan:{keywords:["sd","flag","nation","country","banner"],char:"🇸🇩",fitzpatrick_scale:false,category:"flags"},suriname:{keywords:["sr","flag","nation","country","banner"],char:"🇸🇷",fitzpatrick_scale:false,category:"flags"},swaziland:{keywords:["sz","flag","nation","country","banner"],char:"🇸🇿",fitzpatrick_scale:false,category:"flags"},sweden:{keywords:["se","flag","nation","country","banner"],char:"🇸🇪",fitzpatrick_scale:false,category:"flags"},switzerland:{keywords:["ch","flag","nation","country","banner"],char:"🇨🇭",fitzpatrick_scale:false,category:"flags"},syria:{keywords:["syrian","arab","republic","flag","nation","country","banner"],char:"🇸🇾",fitzpatrick_scale:false,category:"flags"},taiwan:{keywords:["tw","flag","nation","country","banner"],char:"🇹🇼",fitzpatrick_scale:false,category:"flags"},tajikistan:{keywords:["tj","flag","nation","country","banner"],char:"🇹🇯",fitzpatrick_scale:false,category:"flags"},tanzania:{keywords:["tanzania,","united","republic","flag","nation","country","banner"],char:"🇹🇿",fitzpatrick_scale:false,category:"flags"},thailand:{keywords:["th","flag","nation","country","banner"],char:"🇹🇭",fitzpatrick_scale:false,category:"flags"},timor_leste:{keywords:["timor","leste","flag","nation","country","banner"],char:"🇹🇱",fitzpatrick_scale:false,category:"flags"},togo:{keywords:["tg","flag","nation","country","banner"],char:"🇹🇬",fitzpatrick_scale:false,category:"flags"},tokelau:{keywords:["tk","flag","nation","country","banner"],char:"🇹🇰",fitzpatrick_scale:false,category:"flags"},tonga:{keywords:["to","flag","nation","country","banner"],char:"🇹🇴",fitzpatrick_scale:false,category:"flags"},trinidad_tobago:{keywords:["trinidad","tobago","flag","nation","country","banner"],char:"🇹🇹",fitzpatrick_scale:false,category:"flags"},tunisia:{keywords:["tn","flag","nation","country","banner"],char:"🇹🇳",fitzpatrick_scale:false,category:"flags"},tr:{keywords:["turkey","flag","nation","country","banner"],char:"🇹🇷",fitzpatrick_scale:false,category:"flags"},turkmenistan:{keywords:["flag","nation","country","banner"],char:"🇹🇲",fitzpatrick_scale:false,category:"flags"},turks_caicos_islands:{keywords:["turks","caicos","islands","flag","nation","country","banner"],char:"🇹🇨",fitzpatrick_scale:false,category:"flags"},tuvalu:{keywords:["flag","nation","country","banner"],char:"🇹🇻",fitzpatrick_scale:false,category:"flags"},uganda:{keywords:["ug","flag","nation","country","banner"],char:"🇺🇬",fitzpatrick_scale:false,category:"flags"},ukraine:{keywords:["ua","flag","nation","country","banner"],char:"🇺🇦",fitzpatrick_scale:false,category:"flags"},united_arab_emirates:{keywords:["united","arab","emirates","flag","nation","country","banner"],char:"🇦🇪",fitzpatrick_scale:false,category:"flags"},uk:{keywords:["united","kingdom","great","britain","northern","ireland","flag","nation","country","banner","british","UK","english","england","union jack"],char:"🇬🇧",fitzpatrick_scale:false,category:"flags"},england:{keywords:["flag","english"],char:"🏴󠁧󠁢󠁥󠁮󠁧󠁿",fitzpatrick_scale:false,category:"flags"},scotland:{keywords:["flag","scottish"],char:"🏴󠁧󠁢󠁳󠁣󠁴󠁿",fitzpatrick_scale:false,category:"flags"},wales:{keywords:["flag","welsh"],char:"🏴󠁧󠁢󠁷󠁬󠁳󠁿",fitzpatrick_scale:false,category:"flags"},us:{keywords:["united","states","america","flag","nation","country","banner"],char:"🇺🇸",fitzpatrick_scale:false,category:"flags"},us_virgin_islands:{keywords:["virgin","islands","us","flag","nation","country","banner"],char:"🇻🇮",fitzpatrick_scale:false,category:"flags"},uruguay:{keywords:["uy","flag","nation","country","banner"],char:"🇺🇾",fitzpatrick_scale:false,category:"flags"},uzbekistan:{keywords:["uz","flag","nation","country","banner"],char:"🇺🇿",fitzpatrick_scale:false,category:"flags"},vanuatu:{keywords:["vu","flag","nation","country","banner"],char:"🇻🇺",fitzpatrick_scale:false,category:"flags"},vatican_city:{keywords:["vatican","city","flag","nation","country","banner"],char:"🇻🇦",fitzpatrick_scale:false,category:"flags"},venezuela:{keywords:["ve","bolivarian","republic","flag","nation","country","banner"],char:"🇻🇪",fitzpatrick_scale:false,category:"flags"},vietnam:{keywords:["viet","nam","flag","nation","country","banner"],char:"🇻🇳",fitzpatrick_scale:false,category:"flags"},wallis_futuna:{keywords:["wallis","futuna","flag","nation","country","banner"],char:"🇼🇫",fitzpatrick_scale:false,category:"flags"},western_sahara:{keywords:["western","sahara","flag","nation","country","banner"],char:"🇪🇭",fitzpatrick_scale:false,category:"flags"},yemen:{keywords:["ye","flag","nation","country","banner"],char:"🇾🇪",fitzpatrick_scale:false,category:"flags"},zambia:{keywords:["zm","flag","nation","country","banner"],char:"🇿🇲",fitzpatrick_scale:false,category:"flags"},zimbabwe:{keywords:["zw","flag","nation","country","banner"],char:"🇿🇼",fitzpatrick_scale:false,category:"flags"},united_nations:{keywords:["un","flag","banner"],char:"🇺🇳",fitzpatrick_scale:false,category:"flags"},pirate_flag:{keywords:["skull","crossbones","flag","banner"],char:"🏴‍☠️",fitzpatrick_scale:false,category:"flags"}}); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/emoticons/js/emojis.min.js b/public/plugins/tinymce/plugins/emoticons/js/emojis.min.js new file mode 100644 index 000000000..5a1c49160 --- /dev/null +++ b/public/plugins/tinymce/plugins/emoticons/js/emojis.min.js @@ -0,0 +1,2 @@ +// Source: npm package: emojilib, file:emojis.json +window.tinymce.Resource.add("tinymce.plugins.emoticons",{grinning:{keywords:["face","smile","happy","joy",":D","grin"],char:"\u{1f600}",fitzpatrick_scale:!1,category:"people"},grimacing:{keywords:["face","grimace","teeth"],char:"\u{1f62c}",fitzpatrick_scale:!1,category:"people"},grin:{keywords:["face","happy","smile","joy","kawaii"],char:"\u{1f601}",fitzpatrick_scale:!1,category:"people"},joy:{keywords:["face","cry","tears","weep","happy","happytears","haha"],char:"\u{1f602}",fitzpatrick_scale:!1,category:"people"},rofl:{keywords:["face","rolling","floor","laughing","lol","haha"],char:"\u{1f923}",fitzpatrick_scale:!1,category:"people"},partying:{keywords:["face","celebration","woohoo"],char:"\u{1f973}",fitzpatrick_scale:!1,category:"people"},smiley:{keywords:["face","happy","joy","haha",":D",":)","smile","funny"],char:"\u{1f603}",fitzpatrick_scale:!1,category:"people"},smile:{keywords:["face","happy","joy","funny","haha","laugh","like",":D",":)"],char:"\u{1f604}",fitzpatrick_scale:!1,category:"people"},sweat_smile:{keywords:["face","hot","happy","laugh","sweat","smile","relief"],char:"\u{1f605}",fitzpatrick_scale:!1,category:"people"},laughing:{keywords:["happy","joy","lol","satisfied","haha","face","glad","XD","laugh"],char:"\u{1f606}",fitzpatrick_scale:!1,category:"people"},innocent:{keywords:["face","angel","heaven","halo"],char:"\u{1f607}",fitzpatrick_scale:!1,category:"people"},wink:{keywords:["face","happy","mischievous","secret",";)","smile","eye"],char:"\u{1f609}",fitzpatrick_scale:!1,category:"people"},blush:{keywords:["face","smile","happy","flushed","crush","embarrassed","shy","joy"],char:"\u{1f60a}",fitzpatrick_scale:!1,category:"people"},slightly_smiling_face:{keywords:["face","smile"],char:"\u{1f642}",fitzpatrick_scale:!1,category:"people"},upside_down_face:{keywords:["face","flipped","silly","smile"],char:"\u{1f643}",fitzpatrick_scale:!1,category:"people"},relaxed:{keywords:["face","blush","massage","happiness"],char:"\u263a\ufe0f",fitzpatrick_scale:!1,category:"people"},yum:{keywords:["happy","joy","tongue","smile","face","silly","yummy","nom","delicious","savouring"],char:"\u{1f60b}",fitzpatrick_scale:!1,category:"people"},relieved:{keywords:["face","relaxed","phew","massage","happiness"],char:"\u{1f60c}",fitzpatrick_scale:!1,category:"people"},heart_eyes:{keywords:["face","love","like","affection","valentines","infatuation","crush","heart"],char:"\u{1f60d}",fitzpatrick_scale:!1,category:"people"},smiling_face_with_three_hearts:{keywords:["face","love","like","affection","valentines","infatuation","crush","hearts","adore"],char:"\u{1f970}",fitzpatrick_scale:!1,category:"people"},kissing_heart:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:"\u{1f618}",fitzpatrick_scale:!1,category:"people"},kissing:{keywords:["love","like","face","3","valentines","infatuation","kiss"],char:"\u{1f617}",fitzpatrick_scale:!1,category:"people"},kissing_smiling_eyes:{keywords:["face","affection","valentines","infatuation","kiss"],char:"\u{1f619}",fitzpatrick_scale:!1,category:"people"},kissing_closed_eyes:{keywords:["face","love","like","affection","valentines","infatuation","kiss"],char:"\u{1f61a}",fitzpatrick_scale:!1,category:"people"},stuck_out_tongue_winking_eye:{keywords:["face","prank","childish","playful","mischievous","smile","wink","tongue"],char:"\u{1f61c}",fitzpatrick_scale:!1,category:"people"},zany:{keywords:["face","goofy","crazy"],char:"\u{1f92a}",fitzpatrick_scale:!1,category:"people"},raised_eyebrow:{keywords:["face","distrust","scepticism","disapproval","disbelief","surprise"],char:"\u{1f928}",fitzpatrick_scale:!1,category:"people"},monocle:{keywords:["face","stuffy","wealthy"],char:"\u{1f9d0}",fitzpatrick_scale:!1,category:"people"},stuck_out_tongue_closed_eyes:{keywords:["face","prank","playful","mischievous","smile","tongue"],char:"\u{1f61d}",fitzpatrick_scale:!1,category:"people"},stuck_out_tongue:{keywords:["face","prank","childish","playful","mischievous","smile","tongue"],char:"\u{1f61b}",fitzpatrick_scale:!1,category:"people"},money_mouth_face:{keywords:["face","rich","dollar","money"],char:"\u{1f911}",fitzpatrick_scale:!1,category:"people"},nerd_face:{keywords:["face","nerdy","geek","dork"],char:"\u{1f913}",fitzpatrick_scale:!1,category:"people"},sunglasses:{keywords:["face","cool","smile","summer","beach","sunglass"],char:"\u{1f60e}",fitzpatrick_scale:!1,category:"people"},star_struck:{keywords:["face","smile","starry","eyes","grinning"],char:"\u{1f929}",fitzpatrick_scale:!1,category:"people"},clown_face:{keywords:["face"],char:"\u{1f921}",fitzpatrick_scale:!1,category:"people"},cowboy_hat_face:{keywords:["face","cowgirl","hat"],char:"\u{1f920}",fitzpatrick_scale:!1,category:"people"},hugs:{keywords:["face","smile","hug"],char:"\u{1f917}",fitzpatrick_scale:!1,category:"people"},smirk:{keywords:["face","smile","mean","prank","smug","sarcasm"],char:"\u{1f60f}",fitzpatrick_scale:!1,category:"people"},no_mouth:{keywords:["face","hellokitty"],char:"\u{1f636}",fitzpatrick_scale:!1,category:"people"},neutral_face:{keywords:["indifference","meh",":|","neutral"],char:"\u{1f610}",fitzpatrick_scale:!1,category:"people"},expressionless:{keywords:["face","indifferent","-_-","meh","deadpan"],char:"\u{1f611}",fitzpatrick_scale:!1,category:"people"},unamused:{keywords:["indifference","bored","straight face","serious","sarcasm","unimpressed","skeptical","dubious","side_eye"],char:"\u{1f612}",fitzpatrick_scale:!1,category:"people"},roll_eyes:{keywords:["face","eyeroll","frustrated"],char:"\u{1f644}",fitzpatrick_scale:!1,category:"people"},thinking:{keywords:["face","hmmm","think","consider"],char:"\u{1f914}",fitzpatrick_scale:!1,category:"people"},lying_face:{keywords:["face","lie","pinocchio"],char:"\u{1f925}",fitzpatrick_scale:!1,category:"people"},hand_over_mouth:{keywords:["face","whoops","shock","surprise"],char:"\u{1f92d}",fitzpatrick_scale:!1,category:"people"},shushing:{keywords:["face","quiet","shhh"],char:"\u{1f92b}",fitzpatrick_scale:!1,category:"people"},symbols_over_mouth:{keywords:["face","swearing","cursing","cussing","profanity","expletive"],char:"\u{1f92c}",fitzpatrick_scale:!1,category:"people"},exploding_head:{keywords:["face","shocked","mind","blown"],char:"\u{1f92f}",fitzpatrick_scale:!1,category:"people"},flushed:{keywords:["face","blush","shy","flattered"],char:"\u{1f633}",fitzpatrick_scale:!1,category:"people"},disappointed:{keywords:["face","sad","upset","depressed",":("],char:"\u{1f61e}",fitzpatrick_scale:!1,category:"people"},worried:{keywords:["face","concern","nervous",":("],char:"\u{1f61f}",fitzpatrick_scale:!1,category:"people"},angry:{keywords:["mad","face","annoyed","frustrated"],char:"\u{1f620}",fitzpatrick_scale:!1,category:"people"},rage:{keywords:["angry","mad","hate","despise"],char:"\u{1f621}",fitzpatrick_scale:!1,category:"people"},pensive:{keywords:["face","sad","depressed","upset"],char:"\u{1f614}",fitzpatrick_scale:!1,category:"people"},confused:{keywords:["face","indifference","huh","weird","hmmm",":/"],char:"\u{1f615}",fitzpatrick_scale:!1,category:"people"},slightly_frowning_face:{keywords:["face","frowning","disappointed","sad","upset"],char:"\u{1f641}",fitzpatrick_scale:!1,category:"people"},frowning_face:{keywords:["face","sad","upset","frown"],char:"\u2639",fitzpatrick_scale:!1,category:"people"},persevere:{keywords:["face","sick","no","upset","oops"],char:"\u{1f623}",fitzpatrick_scale:!1,category:"people"},confounded:{keywords:["face","confused","sick","unwell","oops",":S"],char:"\u{1f616}",fitzpatrick_scale:!1,category:"people"},tired_face:{keywords:["sick","whine","upset","frustrated"],char:"\u{1f62b}",fitzpatrick_scale:!1,category:"people"},weary:{keywords:["face","tired","sleepy","sad","frustrated","upset"],char:"\u{1f629}",fitzpatrick_scale:!1,category:"people"},pleading:{keywords:["face","begging","mercy"],char:"\u{1f97a}",fitzpatrick_scale:!1,category:"people"},triumph:{keywords:["face","gas","phew","proud","pride"],char:"\u{1f624}",fitzpatrick_scale:!1,category:"people"},open_mouth:{keywords:["face","surprise","impressed","wow","whoa",":O"],char:"\u{1f62e}",fitzpatrick_scale:!1,category:"people"},scream:{keywords:["face","munch","scared","omg"],char:"\u{1f631}",fitzpatrick_scale:!1,category:"people"},fearful:{keywords:["face","scared","terrified","nervous","oops","huh"],char:"\u{1f628}",fitzpatrick_scale:!1,category:"people"},cold_sweat:{keywords:["face","nervous","sweat"],char:"\u{1f630}",fitzpatrick_scale:!1,category:"people"},hushed:{keywords:["face","woo","shh"],char:"\u{1f62f}",fitzpatrick_scale:!1,category:"people"},frowning:{keywords:["face","aw","what"],char:"\u{1f626}",fitzpatrick_scale:!1,category:"people"},anguished:{keywords:["face","stunned","nervous"],char:"\u{1f627}",fitzpatrick_scale:!1,category:"people"},cry:{keywords:["face","tears","sad","depressed","upset",":'("],char:"\u{1f622}",fitzpatrick_scale:!1,category:"people"},disappointed_relieved:{keywords:["face","phew","sweat","nervous"],char:"\u{1f625}",fitzpatrick_scale:!1,category:"people"},drooling_face:{keywords:["face"],char:"\u{1f924}",fitzpatrick_scale:!1,category:"people"},sleepy:{keywords:["face","tired","rest","nap"],char:"\u{1f62a}",fitzpatrick_scale:!1,category:"people"},sweat:{keywords:["face","hot","sad","tired","exercise"],char:"\u{1f613}",fitzpatrick_scale:!1,category:"people"},hot:{keywords:["face","feverish","heat","red","sweating"],char:"\u{1f975}",fitzpatrick_scale:!1,category:"people"},cold:{keywords:["face","blue","freezing","frozen","frostbite","icicles"],char:"\u{1f976}",fitzpatrick_scale:!1,category:"people"},sob:{keywords:["face","cry","tears","sad","upset","depressed"],char:"\u{1f62d}",fitzpatrick_scale:!1,category:"people"},dizzy_face:{keywords:["spent","unconscious","xox","dizzy"],char:"\u{1f635}",fitzpatrick_scale:!1,category:"people"},astonished:{keywords:["face","xox","surprised","poisoned"],char:"\u{1f632}",fitzpatrick_scale:!1,category:"people"},zipper_mouth_face:{keywords:["face","sealed","zipper","secret"],char:"\u{1f910}",fitzpatrick_scale:!1,category:"people"},nauseated_face:{keywords:["face","vomit","gross","green","sick","throw up","ill"],char:"\u{1f922}",fitzpatrick_scale:!1,category:"people"},sneezing_face:{keywords:["face","gesundheit","sneeze","sick","allergy"],char:"\u{1f927}",fitzpatrick_scale:!1,category:"people"},vomiting:{keywords:["face","sick"],char:"\u{1f92e}",fitzpatrick_scale:!1,category:"people"},mask:{keywords:["face","sick","ill","disease"],char:"\u{1f637}",fitzpatrick_scale:!1,category:"people"},face_with_thermometer:{keywords:["sick","temperature","thermometer","cold","fever"],char:"\u{1f912}",fitzpatrick_scale:!1,category:"people"},face_with_head_bandage:{keywords:["injured","clumsy","bandage","hurt"],char:"\u{1f915}",fitzpatrick_scale:!1,category:"people"},woozy:{keywords:["face","dizzy","intoxicated","tipsy","wavy"],char:"\u{1f974}",fitzpatrick_scale:!1,category:"people"},sleeping:{keywords:["face","tired","sleepy","night","zzz"],char:"\u{1f634}",fitzpatrick_scale:!1,category:"people"},zzz:{keywords:["sleepy","tired","dream"],char:"\u{1f4a4}",fitzpatrick_scale:!1,category:"people"},poop:{keywords:["hankey","shitface","fail","turd","shit"],char:"\u{1f4a9}",fitzpatrick_scale:!1,category:"people"},smiling_imp:{keywords:["devil","horns"],char:"\u{1f608}",fitzpatrick_scale:!1,category:"people"},imp:{keywords:["devil","angry","horns"],char:"\u{1f47f}",fitzpatrick_scale:!1,category:"people"},japanese_ogre:{keywords:["monster","red","mask","halloween","scary","creepy","devil","demon","japanese","ogre"],char:"\u{1f479}",fitzpatrick_scale:!1,category:"people"},japanese_goblin:{keywords:["red","evil","mask","monster","scary","creepy","japanese","goblin"],char:"\u{1f47a}",fitzpatrick_scale:!1,category:"people"},skull:{keywords:["dead","skeleton","creepy","death"],char:"\u{1f480}",fitzpatrick_scale:!1,category:"people"},ghost:{keywords:["halloween","spooky","scary"],char:"\u{1f47b}",fitzpatrick_scale:!1,category:"people"},alien:{keywords:["UFO","paul","weird","outer_space"],char:"\u{1f47d}",fitzpatrick_scale:!1,category:"people"},robot:{keywords:["computer","machine","bot"],char:"\u{1f916}",fitzpatrick_scale:!1,category:"people"},smiley_cat:{keywords:["animal","cats","happy","smile"],char:"\u{1f63a}",fitzpatrick_scale:!1,category:"people"},smile_cat:{keywords:["animal","cats","smile"],char:"\u{1f638}",fitzpatrick_scale:!1,category:"people"},joy_cat:{keywords:["animal","cats","haha","happy","tears"],char:"\u{1f639}",fitzpatrick_scale:!1,category:"people"},heart_eyes_cat:{keywords:["animal","love","like","affection","cats","valentines","heart"],char:"\u{1f63b}",fitzpatrick_scale:!1,category:"people"},smirk_cat:{keywords:["animal","cats","smirk"],char:"\u{1f63c}",fitzpatrick_scale:!1,category:"people"},kissing_cat:{keywords:["animal","cats","kiss"],char:"\u{1f63d}",fitzpatrick_scale:!1,category:"people"},scream_cat:{keywords:["animal","cats","munch","scared","scream"],char:"\u{1f640}",fitzpatrick_scale:!1,category:"people"},crying_cat_face:{keywords:["animal","tears","weep","sad","cats","upset","cry"],char:"\u{1f63f}",fitzpatrick_scale:!1,category:"people"},pouting_cat:{keywords:["animal","cats"],char:"\u{1f63e}",fitzpatrick_scale:!1,category:"people"},palms_up:{keywords:["hands","gesture","cupped","prayer"],char:"\u{1f932}",fitzpatrick_scale:!0,category:"people"},raised_hands:{keywords:["gesture","hooray","yea","celebration","hands"],char:"\u{1f64c}",fitzpatrick_scale:!0,category:"people"},clap:{keywords:["hands","praise","applause","congrats","yay"],char:"\u{1f44f}",fitzpatrick_scale:!0,category:"people"},wave:{keywords:["hands","gesture","goodbye","solong","farewell","hello","hi","palm"],char:"\u{1f44b}",fitzpatrick_scale:!0,category:"people"},call_me_hand:{keywords:["hands","gesture"],char:"\u{1f919}",fitzpatrick_scale:!0,category:"people"},"+1":{keywords:["thumbsup","yes","awesome","good","agree","accept","cool","hand","like"],char:"\u{1f44d}",fitzpatrick_scale:!0,category:"people"},"-1":{keywords:["thumbsdown","no","dislike","hand"],char:"\u{1f44e}",fitzpatrick_scale:!0,category:"people"},facepunch:{keywords:["angry","violence","fist","hit","attack","hand"],char:"\u{1f44a}",fitzpatrick_scale:!0,category:"people"},fist:{keywords:["fingers","hand","grasp"],char:"\u270a",fitzpatrick_scale:!0,category:"people"},fist_left:{keywords:["hand","fistbump"],char:"\u{1f91b}",fitzpatrick_scale:!0,category:"people"},fist_right:{keywords:["hand","fistbump"],char:"\u{1f91c}",fitzpatrick_scale:!0,category:"people"},v:{keywords:["fingers","ohyeah","hand","peace","victory","two"],char:"\u270c",fitzpatrick_scale:!0,category:"people"},ok_hand:{keywords:["fingers","limbs","perfect","ok","okay"],char:"\u{1f44c}",fitzpatrick_scale:!0,category:"people"},raised_hand:{keywords:["fingers","stop","highfive","palm","ban"],char:"\u270b",fitzpatrick_scale:!0,category:"people"},raised_back_of_hand:{keywords:["fingers","raised","backhand"],char:"\u{1f91a}",fitzpatrick_scale:!0,category:"people"},open_hands:{keywords:["fingers","butterfly","hands","open"],char:"\u{1f450}",fitzpatrick_scale:!0,category:"people"},muscle:{keywords:["arm","flex","hand","summer","strong","biceps"],char:"\u{1f4aa}",fitzpatrick_scale:!0,category:"people"},pray:{keywords:["please","hope","wish","namaste","highfive"],char:"\u{1f64f}",fitzpatrick_scale:!0,category:"people"},foot:{keywords:["kick","stomp"],char:"\u{1f9b6}",fitzpatrick_scale:!0,category:"people"},leg:{keywords:["kick","limb"],char:"\u{1f9b5}",fitzpatrick_scale:!0,category:"people"},handshake:{keywords:["agreement","shake"],char:"\u{1f91d}",fitzpatrick_scale:!1,category:"people"},point_up:{keywords:["hand","fingers","direction","up"],char:"\u261d",fitzpatrick_scale:!0,category:"people"},point_up_2:{keywords:["fingers","hand","direction","up"],char:"\u{1f446}",fitzpatrick_scale:!0,category:"people"},point_down:{keywords:["fingers","hand","direction","down"],char:"\u{1f447}",fitzpatrick_scale:!0,category:"people"},point_left:{keywords:["direction","fingers","hand","left"],char:"\u{1f448}",fitzpatrick_scale:!0,category:"people"},point_right:{keywords:["fingers","hand","direction","right"],char:"\u{1f449}",fitzpatrick_scale:!0,category:"people"},fu:{keywords:["hand","fingers","rude","middle","flipping"],char:"\u{1f595}",fitzpatrick_scale:!0,category:"people"},raised_hand_with_fingers_splayed:{keywords:["hand","fingers","palm"],char:"\u{1f590}",fitzpatrick_scale:!0,category:"people"},love_you:{keywords:["hand","fingers","gesture"],char:"\u{1f91f}",fitzpatrick_scale:!0,category:"people"},metal:{keywords:["hand","fingers","evil_eye","sign_of_horns","rock_on"],char:"\u{1f918}",fitzpatrick_scale:!0,category:"people"},crossed_fingers:{keywords:["good","lucky"],char:"\u{1f91e}",fitzpatrick_scale:!0,category:"people"},vulcan_salute:{keywords:["hand","fingers","spock","star trek"],char:"\u{1f596}",fitzpatrick_scale:!0,category:"people"},writing_hand:{keywords:["lower_left_ballpoint_pen","stationery","write","compose"],char:"\u270d",fitzpatrick_scale:!0,category:"people"},selfie:{keywords:["camera","phone"],char:"\u{1f933}",fitzpatrick_scale:!0,category:"people"},nail_care:{keywords:["beauty","manicure","finger","fashion","nail"],char:"\u{1f485}",fitzpatrick_scale:!0,category:"people"},lips:{keywords:["mouth","kiss"],char:"\u{1f444}",fitzpatrick_scale:!1,category:"people"},tooth:{keywords:["teeth","dentist"],char:"\u{1f9b7}",fitzpatrick_scale:!1,category:"people"},tongue:{keywords:["mouth","playful"],char:"\u{1f445}",fitzpatrick_scale:!1,category:"people"},ear:{keywords:["face","hear","sound","listen"],char:"\u{1f442}",fitzpatrick_scale:!0,category:"people"},nose:{keywords:["smell","sniff"],char:"\u{1f443}",fitzpatrick_scale:!0,category:"people"},eye:{keywords:["face","look","see","watch","stare"],char:"\u{1f441}",fitzpatrick_scale:!1,category:"people"},eyes:{keywords:["look","watch","stalk","peek","see"],char:"\u{1f440}",fitzpatrick_scale:!1,category:"people"},brain:{keywords:["smart","intelligent"],char:"\u{1f9e0}",fitzpatrick_scale:!1,category:"people"},bust_in_silhouette:{keywords:["user","person","human"],char:"\u{1f464}",fitzpatrick_scale:!1,category:"people"},busts_in_silhouette:{keywords:["user","person","human","group","team"],char:"\u{1f465}",fitzpatrick_scale:!1,category:"people"},speaking_head:{keywords:["user","person","human","sing","say","talk"],char:"\u{1f5e3}",fitzpatrick_scale:!1,category:"people"},baby:{keywords:["child","boy","girl","toddler"],char:"\u{1f476}",fitzpatrick_scale:!0,category:"people"},child:{keywords:["gender-neutral","young"],char:"\u{1f9d2}",fitzpatrick_scale:!0,category:"people"},boy:{keywords:["man","male","guy","teenager"],char:"\u{1f466}",fitzpatrick_scale:!0,category:"people"},girl:{keywords:["female","woman","teenager"],char:"\u{1f467}",fitzpatrick_scale:!0,category:"people"},adult:{keywords:["gender-neutral","person"],char:"\u{1f9d1}",fitzpatrick_scale:!0,category:"people"},man:{keywords:["mustache","father","dad","guy","classy","sir","moustache"],char:"\u{1f468}",fitzpatrick_scale:!0,category:"people"},woman:{keywords:["female","girls","lady"],char:"\u{1f469}",fitzpatrick_scale:!0,category:"people"},blonde_woman:{keywords:["woman","female","girl","blonde","person"],char:"\u{1f471}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},blonde_man:{keywords:["man","male","boy","blonde","guy","person"],char:"\u{1f471}",fitzpatrick_scale:!0,category:"people"},bearded_person:{keywords:["person","bewhiskered"],char:"\u{1f9d4}",fitzpatrick_scale:!0,category:"people"},older_adult:{keywords:["human","elder","senior","gender-neutral"],char:"\u{1f9d3}",fitzpatrick_scale:!0,category:"people"},older_man:{keywords:["human","male","men","old","elder","senior"],char:"\u{1f474}",fitzpatrick_scale:!0,category:"people"},older_woman:{keywords:["human","female","women","lady","old","elder","senior"],char:"\u{1f475}",fitzpatrick_scale:!0,category:"people"},man_with_gua_pi_mao:{keywords:["male","boy","chinese"],char:"\u{1f472}",fitzpatrick_scale:!0,category:"people"},woman_with_headscarf:{keywords:["female","hijab","mantilla","tichel"],char:"\u{1f9d5}",fitzpatrick_scale:!0,category:"people"},woman_with_turban:{keywords:["female","indian","hinduism","arabs","woman"],char:"\u{1f473}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_with_turban:{keywords:["male","indian","hinduism","arabs"],char:"\u{1f473}",fitzpatrick_scale:!0,category:"people"},policewoman:{keywords:["woman","police","law","legal","enforcement","arrest","911","female"],char:"\u{1f46e}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},policeman:{keywords:["man","police","law","legal","enforcement","arrest","911"],char:"\u{1f46e}",fitzpatrick_scale:!0,category:"people"},construction_worker_woman:{keywords:["female","human","wip","build","construction","worker","labor","woman"],char:"\u{1f477}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},construction_worker_man:{keywords:["male","human","wip","guy","build","construction","worker","labor"],char:"\u{1f477}",fitzpatrick_scale:!0,category:"people"},guardswoman:{keywords:["uk","gb","british","female","royal","woman"],char:"\u{1f482}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},guardsman:{keywords:["uk","gb","british","male","guy","royal"],char:"\u{1f482}",fitzpatrick_scale:!0,category:"people"},female_detective:{keywords:["human","spy","detective","female","woman"],char:"\u{1f575}\ufe0f\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},male_detective:{keywords:["human","spy","detective"],char:"\u{1f575}",fitzpatrick_scale:!0,category:"people"},woman_health_worker:{keywords:["doctor","nurse","therapist","healthcare","woman","human"],char:"\u{1f469}\u200d\u2695\ufe0f",fitzpatrick_scale:!0,category:"people"},man_health_worker:{keywords:["doctor","nurse","therapist","healthcare","man","human"],char:"\u{1f468}\u200d\u2695\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_farmer:{keywords:["rancher","gardener","woman","human"],char:"\u{1f469}\u200d\u{1f33e}",fitzpatrick_scale:!0,category:"people"},man_farmer:{keywords:["rancher","gardener","man","human"],char:"\u{1f468}\u200d\u{1f33e}",fitzpatrick_scale:!0,category:"people"},woman_cook:{keywords:["chef","woman","human"],char:"\u{1f469}\u200d\u{1f373}",fitzpatrick_scale:!0,category:"people"},man_cook:{keywords:["chef","man","human"],char:"\u{1f468}\u200d\u{1f373}",fitzpatrick_scale:!0,category:"people"},woman_student:{keywords:["graduate","woman","human"],char:"\u{1f469}\u200d\u{1f393}",fitzpatrick_scale:!0,category:"people"},man_student:{keywords:["graduate","man","human"],char:"\u{1f468}\u200d\u{1f393}",fitzpatrick_scale:!0,category:"people"},woman_singer:{keywords:["rockstar","entertainer","woman","human"],char:"\u{1f469}\u200d\u{1f3a4}",fitzpatrick_scale:!0,category:"people"},man_singer:{keywords:["rockstar","entertainer","man","human"],char:"\u{1f468}\u200d\u{1f3a4}",fitzpatrick_scale:!0,category:"people"},woman_teacher:{keywords:["instructor","professor","woman","human"],char:"\u{1f469}\u200d\u{1f3eb}",fitzpatrick_scale:!0,category:"people"},man_teacher:{keywords:["instructor","professor","man","human"],char:"\u{1f468}\u200d\u{1f3eb}",fitzpatrick_scale:!0,category:"people"},woman_factory_worker:{keywords:["assembly","industrial","woman","human"],char:"\u{1f469}\u200d\u{1f3ed}",fitzpatrick_scale:!0,category:"people"},man_factory_worker:{keywords:["assembly","industrial","man","human"],char:"\u{1f468}\u200d\u{1f3ed}",fitzpatrick_scale:!0,category:"people"},woman_technologist:{keywords:["coder","developer","engineer","programmer","software","woman","human","laptop","computer"],char:"\u{1f469}\u200d\u{1f4bb}",fitzpatrick_scale:!0,category:"people"},man_technologist:{keywords:["coder","developer","engineer","programmer","software","man","human","laptop","computer"],char:"\u{1f468}\u200d\u{1f4bb}",fitzpatrick_scale:!0,category:"people"},woman_office_worker:{keywords:["business","manager","woman","human"],char:"\u{1f469}\u200d\u{1f4bc}",fitzpatrick_scale:!0,category:"people"},man_office_worker:{keywords:["business","manager","man","human"],char:"\u{1f468}\u200d\u{1f4bc}",fitzpatrick_scale:!0,category:"people"},woman_mechanic:{keywords:["plumber","woman","human","wrench"],char:"\u{1f469}\u200d\u{1f527}",fitzpatrick_scale:!0,category:"people"},man_mechanic:{keywords:["plumber","man","human","wrench"],char:"\u{1f468}\u200d\u{1f527}",fitzpatrick_scale:!0,category:"people"},woman_scientist:{keywords:["biologist","chemist","engineer","physicist","woman","human"],char:"\u{1f469}\u200d\u{1f52c}",fitzpatrick_scale:!0,category:"people"},man_scientist:{keywords:["biologist","chemist","engineer","physicist","man","human"],char:"\u{1f468}\u200d\u{1f52c}",fitzpatrick_scale:!0,category:"people"},woman_artist:{keywords:["painter","woman","human"],char:"\u{1f469}\u200d\u{1f3a8}",fitzpatrick_scale:!0,category:"people"},man_artist:{keywords:["painter","man","human"],char:"\u{1f468}\u200d\u{1f3a8}",fitzpatrick_scale:!0,category:"people"},woman_firefighter:{keywords:["fireman","woman","human"],char:"\u{1f469}\u200d\u{1f692}",fitzpatrick_scale:!0,category:"people"},man_firefighter:{keywords:["fireman","man","human"],char:"\u{1f468}\u200d\u{1f692}",fitzpatrick_scale:!0,category:"people"},woman_pilot:{keywords:["aviator","plane","woman","human"],char:"\u{1f469}\u200d\u2708\ufe0f",fitzpatrick_scale:!0,category:"people"},man_pilot:{keywords:["aviator","plane","man","human"],char:"\u{1f468}\u200d\u2708\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_astronaut:{keywords:["space","rocket","woman","human"],char:"\u{1f469}\u200d\u{1f680}",fitzpatrick_scale:!0,category:"people"},man_astronaut:{keywords:["space","rocket","man","human"],char:"\u{1f468}\u200d\u{1f680}",fitzpatrick_scale:!0,category:"people"},woman_judge:{keywords:["justice","court","woman","human"],char:"\u{1f469}\u200d\u2696\ufe0f",fitzpatrick_scale:!0,category:"people"},man_judge:{keywords:["justice","court","man","human"],char:"\u{1f468}\u200d\u2696\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_superhero:{keywords:["woman","female","good","heroine","superpowers"],char:"\u{1f9b8}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_superhero:{keywords:["man","male","good","hero","superpowers"],char:"\u{1f9b8}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_supervillain:{keywords:["woman","female","evil","bad","criminal","heroine","superpowers"],char:"\u{1f9b9}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_supervillain:{keywords:["man","male","evil","bad","criminal","hero","superpowers"],char:"\u{1f9b9}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},mrs_claus:{keywords:["woman","female","xmas","mother christmas"],char:"\u{1f936}",fitzpatrick_scale:!0,category:"people"},santa:{keywords:["festival","man","male","xmas","father christmas"],char:"\u{1f385}",fitzpatrick_scale:!0,category:"people"},sorceress:{keywords:["woman","female","mage","witch"],char:"\u{1f9d9}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},wizard:{keywords:["man","male","mage","sorcerer"],char:"\u{1f9d9}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_elf:{keywords:["woman","female"],char:"\u{1f9dd}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_elf:{keywords:["man","male"],char:"\u{1f9dd}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_vampire:{keywords:["woman","female"],char:"\u{1f9db}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_vampire:{keywords:["man","male","dracula"],char:"\u{1f9db}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_zombie:{keywords:["woman","female","undead","walking dead"],char:"\u{1f9df}\u200d\u2640\ufe0f",fitzpatrick_scale:!1,category:"people"},man_zombie:{keywords:["man","male","dracula","undead","walking dead"],char:"\u{1f9df}\u200d\u2642\ufe0f",fitzpatrick_scale:!1,category:"people"},woman_genie:{keywords:["woman","female"],char:"\u{1f9de}\u200d\u2640\ufe0f",fitzpatrick_scale:!1,category:"people"},man_genie:{keywords:["man","male"],char:"\u{1f9de}\u200d\u2642\ufe0f",fitzpatrick_scale:!1,category:"people"},mermaid:{keywords:["woman","female","merwoman","ariel"],char:"\u{1f9dc}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},merman:{keywords:["man","male","triton"],char:"\u{1f9dc}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_fairy:{keywords:["woman","female"],char:"\u{1f9da}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_fairy:{keywords:["man","male"],char:"\u{1f9da}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},angel:{keywords:["heaven","wings","halo"],char:"\u{1f47c}",fitzpatrick_scale:!0,category:"people"},pregnant_woman:{keywords:["baby"],char:"\u{1f930}",fitzpatrick_scale:!0,category:"people"},breastfeeding:{keywords:["nursing","baby"],char:"\u{1f931}",fitzpatrick_scale:!0,category:"people"},princess:{keywords:["girl","woman","female","blond","crown","royal","queen"],char:"\u{1f478}",fitzpatrick_scale:!0,category:"people"},prince:{keywords:["boy","man","male","crown","royal","king"],char:"\u{1f934}",fitzpatrick_scale:!0,category:"people"},bride_with_veil:{keywords:["couple","marriage","wedding","woman","bride"],char:"\u{1f470}",fitzpatrick_scale:!0,category:"people"},man_in_tuxedo:{keywords:["couple","marriage","wedding","groom"],char:"\u{1f935}",fitzpatrick_scale:!0,category:"people"},running_woman:{keywords:["woman","walking","exercise","race","running","female"],char:"\u{1f3c3}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},running_man:{keywords:["man","walking","exercise","race","running"],char:"\u{1f3c3}",fitzpatrick_scale:!0,category:"people"},walking_woman:{keywords:["human","feet","steps","woman","female"],char:"\u{1f6b6}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},walking_man:{keywords:["human","feet","steps"],char:"\u{1f6b6}",fitzpatrick_scale:!0,category:"people"},dancer:{keywords:["female","girl","woman","fun"],char:"\u{1f483}",fitzpatrick_scale:!0,category:"people"},man_dancing:{keywords:["male","boy","fun","dancer"],char:"\u{1f57a}",fitzpatrick_scale:!0,category:"people"},dancing_women:{keywords:["female","bunny","women","girls"],char:"\u{1f46f}",fitzpatrick_scale:!1,category:"people"},dancing_men:{keywords:["male","bunny","men","boys"],char:"\u{1f46f}\u200d\u2642\ufe0f",fitzpatrick_scale:!1,category:"people"},couple:{keywords:["pair","people","human","love","date","dating","like","affection","valentines","marriage"],char:"\u{1f46b}",fitzpatrick_scale:!1,category:"people"},two_men_holding_hands:{keywords:["pair","couple","love","like","bromance","friendship","people","human"],char:"\u{1f46c}",fitzpatrick_scale:!1,category:"people"},two_women_holding_hands:{keywords:["pair","friendship","couple","love","like","female","people","human"],char:"\u{1f46d}",fitzpatrick_scale:!1,category:"people"},bowing_woman:{keywords:["woman","female","girl"],char:"\u{1f647}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},bowing_man:{keywords:["man","male","boy"],char:"\u{1f647}",fitzpatrick_scale:!0,category:"people"},man_facepalming:{keywords:["man","male","boy","disbelief"],char:"\u{1f926}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_facepalming:{keywords:["woman","female","girl","disbelief"],char:"\u{1f926}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_shrugging:{keywords:["woman","female","girl","confused","indifferent","doubt"],char:"\u{1f937}",fitzpatrick_scale:!0,category:"people"},man_shrugging:{keywords:["man","male","boy","confused","indifferent","doubt"],char:"\u{1f937}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},tipping_hand_woman:{keywords:["female","girl","woman","human","information"],char:"\u{1f481}",fitzpatrick_scale:!0,category:"people"},tipping_hand_man:{keywords:["male","boy","man","human","information"],char:"\u{1f481}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},no_good_woman:{keywords:["female","girl","woman","nope"],char:"\u{1f645}",fitzpatrick_scale:!0,category:"people"},no_good_man:{keywords:["male","boy","man","nope"],char:"\u{1f645}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},ok_woman:{keywords:["women","girl","female","pink","human","woman"],char:"\u{1f646}",fitzpatrick_scale:!0,category:"people"},ok_man:{keywords:["men","boy","male","blue","human","man"],char:"\u{1f646}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},raising_hand_woman:{keywords:["female","girl","woman"],char:"\u{1f64b}",fitzpatrick_scale:!0,category:"people"},raising_hand_man:{keywords:["male","boy","man"],char:"\u{1f64b}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},pouting_woman:{keywords:["female","girl","woman"],char:"\u{1f64e}",fitzpatrick_scale:!0,category:"people"},pouting_man:{keywords:["male","boy","man"],char:"\u{1f64e}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},frowning_woman:{keywords:["female","girl","woman","sad","depressed","discouraged","unhappy"],char:"\u{1f64d}",fitzpatrick_scale:!0,category:"people"},frowning_man:{keywords:["male","boy","man","sad","depressed","discouraged","unhappy"],char:"\u{1f64d}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},haircut_woman:{keywords:["female","girl","woman"],char:"\u{1f487}",fitzpatrick_scale:!0,category:"people"},haircut_man:{keywords:["male","boy","man"],char:"\u{1f487}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},massage_woman:{keywords:["female","girl","woman","head"],char:"\u{1f486}",fitzpatrick_scale:!0,category:"people"},massage_man:{keywords:["male","boy","man","head"],char:"\u{1f486}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},woman_in_steamy_room:{keywords:["female","woman","spa","steamroom","sauna"],char:"\u{1f9d6}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"people"},man_in_steamy_room:{keywords:["male","man","spa","steamroom","sauna"],char:"\u{1f9d6}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"people"},couple_with_heart_woman_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:"\u{1f491}",fitzpatrick_scale:!1,category:"people"},couple_with_heart_woman_woman:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:"\u{1f469}\u200d\u2764\ufe0f\u200d\u{1f469}",fitzpatrick_scale:!1,category:"people"},couple_with_heart_man_man:{keywords:["pair","love","like","affection","human","dating","valentines","marriage"],char:"\u{1f468}\u200d\u2764\ufe0f\u200d\u{1f468}",fitzpatrick_scale:!1,category:"people"},couplekiss_man_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:"\u{1f48f}",fitzpatrick_scale:!1,category:"people"},couplekiss_woman_woman:{keywords:["pair","valentines","love","like","dating","marriage"],char:"\u{1f469}\u200d\u2764\ufe0f\u200d\u{1f48b}\u200d\u{1f469}",fitzpatrick_scale:!1,category:"people"},couplekiss_man_man:{keywords:["pair","valentines","love","like","dating","marriage"],char:"\u{1f468}\u200d\u2764\ufe0f\u200d\u{1f48b}\u200d\u{1f468}",fitzpatrick_scale:!1,category:"people"},family_man_woman_boy:{keywords:["home","parents","child","mom","dad","father","mother","people","human"],char:"\u{1f46a}",fitzpatrick_scale:!1,category:"people"},family_man_woman_girl:{keywords:["home","parents","people","human","child"],char:"\u{1f468}\u200d\u{1f469}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_man_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f469}\u200d\u{1f466}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_woman_woman_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f469}\u200d\u{1f469}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl:{keywords:["home","parents","people","human","children"],char:"\u{1f469}\u200d\u{1f469}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f469}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_woman_woman_boy_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f469}\u200d\u{1f469}\u200d\u{1f466}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_woman_woman_girl_girl:{keywords:["home","parents","people","human","children"],char:"\u{1f469}\u200d\u{1f469}\u200d\u{1f467}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_man_man_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f468}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_man_girl:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f468}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_man_man_girl_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f468}\u200d\u{1f467}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_man_boy_boy:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f468}\u200d\u{1f466}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_man_girl_girl:{keywords:["home","parents","people","human","children"],char:"\u{1f468}\u200d\u{1f468}\u200d\u{1f467}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_woman_boy:{keywords:["home","parent","people","human","child"],char:"\u{1f469}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_woman_girl:{keywords:["home","parent","people","human","child"],char:"\u{1f469}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_woman_girl_boy:{keywords:["home","parent","people","human","children"],char:"\u{1f469}\u200d\u{1f467}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_woman_boy_boy:{keywords:["home","parent","people","human","children"],char:"\u{1f469}\u200d\u{1f466}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_woman_girl_girl:{keywords:["home","parent","people","human","children"],char:"\u{1f469}\u200d\u{1f467}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_man_boy:{keywords:["home","parent","people","human","child"],char:"\u{1f468}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_girl:{keywords:["home","parent","people","human","child"],char:"\u{1f468}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},family_man_girl_boy:{keywords:["home","parent","people","human","children"],char:"\u{1f468}\u200d\u{1f467}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_boy_boy:{keywords:["home","parent","people","human","children"],char:"\u{1f468}\u200d\u{1f466}\u200d\u{1f466}",fitzpatrick_scale:!1,category:"people"},family_man_girl_girl:{keywords:["home","parent","people","human","children"],char:"\u{1f468}\u200d\u{1f467}\u200d\u{1f467}",fitzpatrick_scale:!1,category:"people"},yarn:{keywords:["ball","crochet","knit"],char:"\u{1f9f6}",fitzpatrick_scale:!1,category:"people"},thread:{keywords:["needle","sewing","spool","string"],char:"\u{1f9f5}",fitzpatrick_scale:!1,category:"people"},coat:{keywords:["jacket"],char:"\u{1f9e5}",fitzpatrick_scale:!1,category:"people"},labcoat:{keywords:["doctor","experiment","scientist","chemist"],char:"\u{1f97c}",fitzpatrick_scale:!1,category:"people"},womans_clothes:{keywords:["fashion","shopping_bags","female"],char:"\u{1f45a}",fitzpatrick_scale:!1,category:"people"},tshirt:{keywords:["fashion","cloth","casual","shirt","tee"],char:"\u{1f455}",fitzpatrick_scale:!1,category:"people"},jeans:{keywords:["fashion","shopping"],char:"\u{1f456}",fitzpatrick_scale:!1,category:"people"},necktie:{keywords:["shirt","suitup","formal","fashion","cloth","business"],char:"\u{1f454}",fitzpatrick_scale:!1,category:"people"},dress:{keywords:["clothes","fashion","shopping"],char:"\u{1f457}",fitzpatrick_scale:!1,category:"people"},bikini:{keywords:["swimming","female","woman","girl","fashion","beach","summer"],char:"\u{1f459}",fitzpatrick_scale:!1,category:"people"},kimono:{keywords:["dress","fashion","women","female","japanese"],char:"\u{1f458}",fitzpatrick_scale:!1,category:"people"},lipstick:{keywords:["female","girl","fashion","woman"],char:"\u{1f484}",fitzpatrick_scale:!1,category:"people"},kiss:{keywords:["face","lips","love","like","affection","valentines"],char:"\u{1f48b}",fitzpatrick_scale:!1,category:"people"},footprints:{keywords:["feet","tracking","walking","beach"],char:"\u{1f463}",fitzpatrick_scale:!1,category:"people"},flat_shoe:{keywords:["ballet","slip-on","slipper"],char:"\u{1f97f}",fitzpatrick_scale:!1,category:"people"},high_heel:{keywords:["fashion","shoes","female","pumps","stiletto"],char:"\u{1f460}",fitzpatrick_scale:!1,category:"people"},sandal:{keywords:["shoes","fashion","flip flops"],char:"\u{1f461}",fitzpatrick_scale:!1,category:"people"},boot:{keywords:["shoes","fashion"],char:"\u{1f462}",fitzpatrick_scale:!1,category:"people"},mans_shoe:{keywords:["fashion","male"],char:"\u{1f45e}",fitzpatrick_scale:!1,category:"people"},athletic_shoe:{keywords:["shoes","sports","sneakers"],char:"\u{1f45f}",fitzpatrick_scale:!1,category:"people"},hiking_boot:{keywords:["backpacking","camping","hiking"],char:"\u{1f97e}",fitzpatrick_scale:!1,category:"people"},socks:{keywords:["stockings","clothes"],char:"\u{1f9e6}",fitzpatrick_scale:!1,category:"people"},gloves:{keywords:["hands","winter","clothes"],char:"\u{1f9e4}",fitzpatrick_scale:!1,category:"people"},scarf:{keywords:["neck","winter","clothes"],char:"\u{1f9e3}",fitzpatrick_scale:!1,category:"people"},womans_hat:{keywords:["fashion","accessories","female","lady","spring"],char:"\u{1f452}",fitzpatrick_scale:!1,category:"people"},tophat:{keywords:["magic","gentleman","classy","circus"],char:"\u{1f3a9}",fitzpatrick_scale:!1,category:"people"},billed_hat:{keywords:["cap","baseball"],char:"\u{1f9e2}",fitzpatrick_scale:!1,category:"people"},rescue_worker_helmet:{keywords:["construction","build"],char:"\u26d1",fitzpatrick_scale:!1,category:"people"},mortar_board:{keywords:["school","college","degree","university","graduation","cap","hat","legal","learn","education"],char:"\u{1f393}",fitzpatrick_scale:!1,category:"people"},crown:{keywords:["king","kod","leader","royalty","lord"],char:"\u{1f451}",fitzpatrick_scale:!1,category:"people"},school_satchel:{keywords:["student","education","bag","backpack"],char:"\u{1f392}",fitzpatrick_scale:!1,category:"people"},luggage:{keywords:["packing","travel"],char:"\u{1f9f3}",fitzpatrick_scale:!1,category:"people"},pouch:{keywords:["bag","accessories","shopping"],char:"\u{1f45d}",fitzpatrick_scale:!1,category:"people"},purse:{keywords:["fashion","accessories","money","sales","shopping"],char:"\u{1f45b}",fitzpatrick_scale:!1,category:"people"},handbag:{keywords:["fashion","accessory","accessories","shopping"],char:"\u{1f45c}",fitzpatrick_scale:!1,category:"people"},briefcase:{keywords:["business","documents","work","law","legal","job","career"],char:"\u{1f4bc}",fitzpatrick_scale:!1,category:"people"},eyeglasses:{keywords:["fashion","accessories","eyesight","nerdy","dork","geek"],char:"\u{1f453}",fitzpatrick_scale:!1,category:"people"},dark_sunglasses:{keywords:["face","cool","accessories"],char:"\u{1f576}",fitzpatrick_scale:!1,category:"people"},goggles:{keywords:["eyes","protection","safety"],char:"\u{1f97d}",fitzpatrick_scale:!1,category:"people"},ring:{keywords:["wedding","propose","marriage","valentines","diamond","fashion","jewelry","gem","engagement"],char:"\u{1f48d}",fitzpatrick_scale:!1,category:"people"},closed_umbrella:{keywords:["weather","rain","drizzle"],char:"\u{1f302}",fitzpatrick_scale:!1,category:"people"},dog:{keywords:["animal","friend","nature","woof","puppy","pet","faithful"],char:"\u{1f436}",fitzpatrick_scale:!1,category:"animals_and_nature"},cat:{keywords:["animal","meow","nature","pet","kitten"],char:"\u{1f431}",fitzpatrick_scale:!1,category:"animals_and_nature"},mouse:{keywords:["animal","nature","cheese_wedge","rodent"],char:"\u{1f42d}",fitzpatrick_scale:!1,category:"animals_and_nature"},hamster:{keywords:["animal","nature"],char:"\u{1f439}",fitzpatrick_scale:!1,category:"animals_and_nature"},rabbit:{keywords:["animal","nature","pet","spring","magic","bunny"],char:"\u{1f430}",fitzpatrick_scale:!1,category:"animals_and_nature"},fox_face:{keywords:["animal","nature","face"],char:"\u{1f98a}",fitzpatrick_scale:!1,category:"animals_and_nature"},bear:{keywords:["animal","nature","wild"],char:"\u{1f43b}",fitzpatrick_scale:!1,category:"animals_and_nature"},panda_face:{keywords:["animal","nature","panda"],char:"\u{1f43c}",fitzpatrick_scale:!1,category:"animals_and_nature"},koala:{keywords:["animal","nature"],char:"\u{1f428}",fitzpatrick_scale:!1,category:"animals_and_nature"},tiger:{keywords:["animal","cat","danger","wild","nature","roar"],char:"\u{1f42f}",fitzpatrick_scale:!1,category:"animals_and_nature"},lion:{keywords:["animal","nature"],char:"\u{1f981}",fitzpatrick_scale:!1,category:"animals_and_nature"},cow:{keywords:["beef","ox","animal","nature","moo","milk"],char:"\u{1f42e}",fitzpatrick_scale:!1,category:"animals_and_nature"},pig:{keywords:["animal","oink","nature"],char:"\u{1f437}",fitzpatrick_scale:!1,category:"animals_and_nature"},pig_nose:{keywords:["animal","oink"],char:"\u{1f43d}",fitzpatrick_scale:!1,category:"animals_and_nature"},frog:{keywords:["animal","nature","croak","toad"],char:"\u{1f438}",fitzpatrick_scale:!1,category:"animals_and_nature"},squid:{keywords:["animal","nature","ocean","sea"],char:"\u{1f991}",fitzpatrick_scale:!1,category:"animals_and_nature"},octopus:{keywords:["animal","creature","ocean","sea","nature","beach"],char:"\u{1f419}",fitzpatrick_scale:!1,category:"animals_and_nature"},shrimp:{keywords:["animal","ocean","nature","seafood"],char:"\u{1f990}",fitzpatrick_scale:!1,category:"animals_and_nature"},monkey_face:{keywords:["animal","nature","circus"],char:"\u{1f435}",fitzpatrick_scale:!1,category:"animals_and_nature"},gorilla:{keywords:["animal","nature","circus"],char:"\u{1f98d}",fitzpatrick_scale:!1,category:"animals_and_nature"},see_no_evil:{keywords:["monkey","animal","nature","haha"],char:"\u{1f648}",fitzpatrick_scale:!1,category:"animals_and_nature"},hear_no_evil:{keywords:["animal","monkey","nature"],char:"\u{1f649}",fitzpatrick_scale:!1,category:"animals_and_nature"},speak_no_evil:{keywords:["monkey","animal","nature","omg"],char:"\u{1f64a}",fitzpatrick_scale:!1,category:"animals_and_nature"},monkey:{keywords:["animal","nature","banana","circus"],char:"\u{1f412}",fitzpatrick_scale:!1,category:"animals_and_nature"},chicken:{keywords:["animal","cluck","nature","bird"],char:"\u{1f414}",fitzpatrick_scale:!1,category:"animals_and_nature"},penguin:{keywords:["animal","nature"],char:"\u{1f427}",fitzpatrick_scale:!1,category:"animals_and_nature"},bird:{keywords:["animal","nature","fly","tweet","spring"],char:"\u{1f426}",fitzpatrick_scale:!1,category:"animals_and_nature"},baby_chick:{keywords:["animal","chicken","bird"],char:"\u{1f424}",fitzpatrick_scale:!1,category:"animals_and_nature"},hatching_chick:{keywords:["animal","chicken","egg","born","baby","bird"],char:"\u{1f423}",fitzpatrick_scale:!1,category:"animals_and_nature"},hatched_chick:{keywords:["animal","chicken","baby","bird"],char:"\u{1f425}",fitzpatrick_scale:!1,category:"animals_and_nature"},duck:{keywords:["animal","nature","bird","mallard"],char:"\u{1f986}",fitzpatrick_scale:!1,category:"animals_and_nature"},eagle:{keywords:["animal","nature","bird"],char:"\u{1f985}",fitzpatrick_scale:!1,category:"animals_and_nature"},owl:{keywords:["animal","nature","bird","hoot"],char:"\u{1f989}",fitzpatrick_scale:!1,category:"animals_and_nature"},bat:{keywords:["animal","nature","blind","vampire"],char:"\u{1f987}",fitzpatrick_scale:!1,category:"animals_and_nature"},wolf:{keywords:["animal","nature","wild"],char:"\u{1f43a}",fitzpatrick_scale:!1,category:"animals_and_nature"},boar:{keywords:["animal","nature"],char:"\u{1f417}",fitzpatrick_scale:!1,category:"animals_and_nature"},horse:{keywords:["animal","brown","nature"],char:"\u{1f434}",fitzpatrick_scale:!1,category:"animals_and_nature"},unicorn:{keywords:["animal","nature","mystical"],char:"\u{1f984}",fitzpatrick_scale:!1,category:"animals_and_nature"},honeybee:{keywords:["animal","insect","nature","bug","spring","honey"],char:"\u{1f41d}",fitzpatrick_scale:!1,category:"animals_and_nature"},bug:{keywords:["animal","insect","nature","worm"],char:"\u{1f41b}",fitzpatrick_scale:!1,category:"animals_and_nature"},butterfly:{keywords:["animal","insect","nature","caterpillar"],char:"\u{1f98b}",fitzpatrick_scale:!1,category:"animals_and_nature"},snail:{keywords:["slow","animal","shell"],char:"\u{1f40c}",fitzpatrick_scale:!1,category:"animals_and_nature"},beetle:{keywords:["animal","insect","nature","ladybug"],char:"\u{1f41e}",fitzpatrick_scale:!1,category:"animals_and_nature"},ant:{keywords:["animal","insect","nature","bug"],char:"\u{1f41c}",fitzpatrick_scale:!1,category:"animals_and_nature"},grasshopper:{keywords:["animal","cricket","chirp"],char:"\u{1f997}",fitzpatrick_scale:!1,category:"animals_and_nature"},spider:{keywords:["animal","arachnid"],char:"\u{1f577}",fitzpatrick_scale:!1,category:"animals_and_nature"},scorpion:{keywords:["animal","arachnid"],char:"\u{1f982}",fitzpatrick_scale:!1,category:"animals_and_nature"},crab:{keywords:["animal","crustacean"],char:"\u{1f980}",fitzpatrick_scale:!1,category:"animals_and_nature"},snake:{keywords:["animal","evil","nature","hiss","python"],char:"\u{1f40d}",fitzpatrick_scale:!1,category:"animals_and_nature"},lizard:{keywords:["animal","nature","reptile"],char:"\u{1f98e}",fitzpatrick_scale:!1,category:"animals_and_nature"},"t-rex":{keywords:["animal","nature","dinosaur","tyrannosaurus","extinct"],char:"\u{1f996}",fitzpatrick_scale:!1,category:"animals_and_nature"},sauropod:{keywords:["animal","nature","dinosaur","brachiosaurus","brontosaurus","diplodocus","extinct"],char:"\u{1f995}",fitzpatrick_scale:!1,category:"animals_and_nature"},turtle:{keywords:["animal","slow","nature","tortoise"],char:"\u{1f422}",fitzpatrick_scale:!1,category:"animals_and_nature"},tropical_fish:{keywords:["animal","swim","ocean","beach","nemo"],char:"\u{1f420}",fitzpatrick_scale:!1,category:"animals_and_nature"},fish:{keywords:["animal","food","nature"],char:"\u{1f41f}",fitzpatrick_scale:!1,category:"animals_and_nature"},blowfish:{keywords:["animal","nature","food","sea","ocean"],char:"\u{1f421}",fitzpatrick_scale:!1,category:"animals_and_nature"},dolphin:{keywords:["animal","nature","fish","sea","ocean","flipper","fins","beach"],char:"\u{1f42c}",fitzpatrick_scale:!1,category:"animals_and_nature"},shark:{keywords:["animal","nature","fish","sea","ocean","jaws","fins","beach"],char:"\u{1f988}",fitzpatrick_scale:!1,category:"animals_and_nature"},whale:{keywords:["animal","nature","sea","ocean"],char:"\u{1f433}",fitzpatrick_scale:!1,category:"animals_and_nature"},whale2:{keywords:["animal","nature","sea","ocean"],char:"\u{1f40b}",fitzpatrick_scale:!1,category:"animals_and_nature"},crocodile:{keywords:["animal","nature","reptile","lizard","alligator"],char:"\u{1f40a}",fitzpatrick_scale:!1,category:"animals_and_nature"},leopard:{keywords:["animal","nature"],char:"\u{1f406}",fitzpatrick_scale:!1,category:"animals_and_nature"},zebra:{keywords:["animal","nature","stripes","safari"],char:"\u{1f993}",fitzpatrick_scale:!1,category:"animals_and_nature"},tiger2:{keywords:["animal","nature","roar"],char:"\u{1f405}",fitzpatrick_scale:!1,category:"animals_and_nature"},water_buffalo:{keywords:["animal","nature","ox","cow"],char:"\u{1f403}",fitzpatrick_scale:!1,category:"animals_and_nature"},ox:{keywords:["animal","cow","beef"],char:"\u{1f402}",fitzpatrick_scale:!1,category:"animals_and_nature"},cow2:{keywords:["beef","ox","animal","nature","moo","milk"],char:"\u{1f404}",fitzpatrick_scale:!1,category:"animals_and_nature"},deer:{keywords:["animal","nature","horns","venison"],char:"\u{1f98c}",fitzpatrick_scale:!1,category:"animals_and_nature"},dromedary_camel:{keywords:["animal","hot","desert","hump"],char:"\u{1f42a}",fitzpatrick_scale:!1,category:"animals_and_nature"},camel:{keywords:["animal","nature","hot","desert","hump"],char:"\u{1f42b}",fitzpatrick_scale:!1,category:"animals_and_nature"},giraffe:{keywords:["animal","nature","spots","safari"],char:"\u{1f992}",fitzpatrick_scale:!1,category:"animals_and_nature"},elephant:{keywords:["animal","nature","nose","th","circus"],char:"\u{1f418}",fitzpatrick_scale:!1,category:"animals_and_nature"},rhinoceros:{keywords:["animal","nature","horn"],char:"\u{1f98f}",fitzpatrick_scale:!1,category:"animals_and_nature"},goat:{keywords:["animal","nature"],char:"\u{1f410}",fitzpatrick_scale:!1,category:"animals_and_nature"},ram:{keywords:["animal","sheep","nature"],char:"\u{1f40f}",fitzpatrick_scale:!1,category:"animals_and_nature"},sheep:{keywords:["animal","nature","wool","shipit"],char:"\u{1f411}",fitzpatrick_scale:!1,category:"animals_and_nature"},racehorse:{keywords:["animal","gamble","luck"],char:"\u{1f40e}",fitzpatrick_scale:!1,category:"animals_and_nature"},pig2:{keywords:["animal","nature"],char:"\u{1f416}",fitzpatrick_scale:!1,category:"animals_and_nature"},rat:{keywords:["animal","mouse","rodent"],char:"\u{1f400}",fitzpatrick_scale:!1,category:"animals_and_nature"},mouse2:{keywords:["animal","nature","rodent"],char:"\u{1f401}",fitzpatrick_scale:!1,category:"animals_and_nature"},rooster:{keywords:["animal","nature","chicken"],char:"\u{1f413}",fitzpatrick_scale:!1,category:"animals_and_nature"},turkey:{keywords:["animal","bird"],char:"\u{1f983}",fitzpatrick_scale:!1,category:"animals_and_nature"},dove:{keywords:["animal","bird"],char:"\u{1f54a}",fitzpatrick_scale:!1,category:"animals_and_nature"},dog2:{keywords:["animal","nature","friend","doge","pet","faithful"],char:"\u{1f415}",fitzpatrick_scale:!1,category:"animals_and_nature"},poodle:{keywords:["dog","animal","101","nature","pet"],char:"\u{1f429}",fitzpatrick_scale:!1,category:"animals_and_nature"},cat2:{keywords:["animal","meow","pet","cats"],char:"\u{1f408}",fitzpatrick_scale:!1,category:"animals_and_nature"},rabbit2:{keywords:["animal","nature","pet","magic","spring"],char:"\u{1f407}",fitzpatrick_scale:!1,category:"animals_and_nature"},chipmunk:{keywords:["animal","nature","rodent","squirrel"],char:"\u{1f43f}",fitzpatrick_scale:!1,category:"animals_and_nature"},hedgehog:{keywords:["animal","nature","spiny"],char:"\u{1f994}",fitzpatrick_scale:!1,category:"animals_and_nature"},raccoon:{keywords:["animal","nature"],char:"\u{1f99d}",fitzpatrick_scale:!1,category:"animals_and_nature"},llama:{keywords:["animal","nature","alpaca"],char:"\u{1f999}",fitzpatrick_scale:!1,category:"animals_and_nature"},hippopotamus:{keywords:["animal","nature"],char:"\u{1f99b}",fitzpatrick_scale:!1,category:"animals_and_nature"},kangaroo:{keywords:["animal","nature","australia","joey","hop","marsupial"],char:"\u{1f998}",fitzpatrick_scale:!1,category:"animals_and_nature"},badger:{keywords:["animal","nature","honey"],char:"\u{1f9a1}",fitzpatrick_scale:!1,category:"animals_and_nature"},swan:{keywords:["animal","nature","bird"],char:"\u{1f9a2}",fitzpatrick_scale:!1,category:"animals_and_nature"},peacock:{keywords:["animal","nature","peahen","bird"],char:"\u{1f99a}",fitzpatrick_scale:!1,category:"animals_and_nature"},parrot:{keywords:["animal","nature","bird","pirate","talk"],char:"\u{1f99c}",fitzpatrick_scale:!1,category:"animals_and_nature"},lobster:{keywords:["animal","nature","bisque","claws","seafood"],char:"\u{1f99e}",fitzpatrick_scale:!1,category:"animals_and_nature"},mosquito:{keywords:["animal","nature","insect","malaria"],char:"\u{1f99f}",fitzpatrick_scale:!1,category:"animals_and_nature"},paw_prints:{keywords:["animal","tracking","footprints","dog","cat","pet","feet"],char:"\u{1f43e}",fitzpatrick_scale:!1,category:"animals_and_nature"},dragon:{keywords:["animal","myth","nature","chinese","green"],char:"\u{1f409}",fitzpatrick_scale:!1,category:"animals_and_nature"},dragon_face:{keywords:["animal","myth","nature","chinese","green"],char:"\u{1f432}",fitzpatrick_scale:!1,category:"animals_and_nature"},cactus:{keywords:["vegetable","plant","nature"],char:"\u{1f335}",fitzpatrick_scale:!1,category:"animals_and_nature"},christmas_tree:{keywords:["festival","vacation","december","xmas","celebration"],char:"\u{1f384}",fitzpatrick_scale:!1,category:"animals_and_nature"},evergreen_tree:{keywords:["plant","nature"],char:"\u{1f332}",fitzpatrick_scale:!1,category:"animals_and_nature"},deciduous_tree:{keywords:["plant","nature"],char:"\u{1f333}",fitzpatrick_scale:!1,category:"animals_and_nature"},palm_tree:{keywords:["plant","vegetable","nature","summer","beach","mojito","tropical"],char:"\u{1f334}",fitzpatrick_scale:!1,category:"animals_and_nature"},seedling:{keywords:["plant","nature","grass","lawn","spring"],char:"\u{1f331}",fitzpatrick_scale:!1,category:"animals_and_nature"},herb:{keywords:["vegetable","plant","medicine","weed","grass","lawn"],char:"\u{1f33f}",fitzpatrick_scale:!1,category:"animals_and_nature"},shamrock:{keywords:["vegetable","plant","nature","irish","clover"],char:"\u2618",fitzpatrick_scale:!1,category:"animals_and_nature"},four_leaf_clover:{keywords:["vegetable","plant","nature","lucky","irish"],char:"\u{1f340}",fitzpatrick_scale:!1,category:"animals_and_nature"},bamboo:{keywords:["plant","nature","vegetable","panda","pine_decoration"],char:"\u{1f38d}",fitzpatrick_scale:!1,category:"animals_and_nature"},tanabata_tree:{keywords:["plant","nature","branch","summer"],char:"\u{1f38b}",fitzpatrick_scale:!1,category:"animals_and_nature"},leaves:{keywords:["nature","plant","tree","vegetable","grass","lawn","spring"],char:"\u{1f343}",fitzpatrick_scale:!1,category:"animals_and_nature"},fallen_leaf:{keywords:["nature","plant","vegetable","leaves"],char:"\u{1f342}",fitzpatrick_scale:!1,category:"animals_and_nature"},maple_leaf:{keywords:["nature","plant","vegetable","ca","fall"],char:"\u{1f341}",fitzpatrick_scale:!1,category:"animals_and_nature"},ear_of_rice:{keywords:["nature","plant"],char:"\u{1f33e}",fitzpatrick_scale:!1,category:"animals_and_nature"},hibiscus:{keywords:["plant","vegetable","flowers","beach"],char:"\u{1f33a}",fitzpatrick_scale:!1,category:"animals_and_nature"},sunflower:{keywords:["nature","plant","fall"],char:"\u{1f33b}",fitzpatrick_scale:!1,category:"animals_and_nature"},rose:{keywords:["flowers","valentines","love","spring"],char:"\u{1f339}",fitzpatrick_scale:!1,category:"animals_and_nature"},wilted_flower:{keywords:["plant","nature","flower"],char:"\u{1f940}",fitzpatrick_scale:!1,category:"animals_and_nature"},tulip:{keywords:["flowers","plant","nature","summer","spring"],char:"\u{1f337}",fitzpatrick_scale:!1,category:"animals_and_nature"},blossom:{keywords:["nature","flowers","yellow"],char:"\u{1f33c}",fitzpatrick_scale:!1,category:"animals_and_nature"},cherry_blossom:{keywords:["nature","plant","spring","flower"],char:"\u{1f338}",fitzpatrick_scale:!1,category:"animals_and_nature"},bouquet:{keywords:["flowers","nature","spring"],char:"\u{1f490}",fitzpatrick_scale:!1,category:"animals_and_nature"},mushroom:{keywords:["plant","vegetable"],char:"\u{1f344}",fitzpatrick_scale:!1,category:"animals_and_nature"},chestnut:{keywords:["food","squirrel"],char:"\u{1f330}",fitzpatrick_scale:!1,category:"animals_and_nature"},jack_o_lantern:{keywords:["halloween","light","pumpkin","creepy","fall"],char:"\u{1f383}",fitzpatrick_scale:!1,category:"animals_and_nature"},shell:{keywords:["nature","sea","beach"],char:"\u{1f41a}",fitzpatrick_scale:!1,category:"animals_and_nature"},spider_web:{keywords:["animal","insect","arachnid","silk"],char:"\u{1f578}",fitzpatrick_scale:!1,category:"animals_and_nature"},earth_americas:{keywords:["globe","world","USA","international"],char:"\u{1f30e}",fitzpatrick_scale:!1,category:"animals_and_nature"},earth_africa:{keywords:["globe","world","international"],char:"\u{1f30d}",fitzpatrick_scale:!1,category:"animals_and_nature"},earth_asia:{keywords:["globe","world","east","international"],char:"\u{1f30f}",fitzpatrick_scale:!1,category:"animals_and_nature"},full_moon:{keywords:["nature","yellow","twilight","planet","space","night","evening","sleep"],char:"\u{1f315}",fitzpatrick_scale:!1,category:"animals_and_nature"},waning_gibbous_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep","waxing_gibbous_moon"],char:"\u{1f316}",fitzpatrick_scale:!1,category:"animals_and_nature"},last_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f317}",fitzpatrick_scale:!1,category:"animals_and_nature"},waning_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f318}",fitzpatrick_scale:!1,category:"animals_and_nature"},new_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f311}",fitzpatrick_scale:!1,category:"animals_and_nature"},waxing_crescent_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f312}",fitzpatrick_scale:!1,category:"animals_and_nature"},first_quarter_moon:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f313}",fitzpatrick_scale:!1,category:"animals_and_nature"},waxing_gibbous_moon:{keywords:["nature","night","sky","gray","twilight","planet","space","evening","sleep"],char:"\u{1f314}",fitzpatrick_scale:!1,category:"animals_and_nature"},new_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f31a}",fitzpatrick_scale:!1,category:"animals_and_nature"},full_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f31d}",fitzpatrick_scale:!1,category:"animals_and_nature"},first_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f31b}",fitzpatrick_scale:!1,category:"animals_and_nature"},last_quarter_moon_with_face:{keywords:["nature","twilight","planet","space","night","evening","sleep"],char:"\u{1f31c}",fitzpatrick_scale:!1,category:"animals_and_nature"},sun_with_face:{keywords:["nature","morning","sky"],char:"\u{1f31e}",fitzpatrick_scale:!1,category:"animals_and_nature"},crescent_moon:{keywords:["night","sleep","sky","evening","magic"],char:"\u{1f319}",fitzpatrick_scale:!1,category:"animals_and_nature"},star:{keywords:["night","yellow"],char:"\u2b50",fitzpatrick_scale:!1,category:"animals_and_nature"},star2:{keywords:["night","sparkle","awesome","good","magic"],char:"\u{1f31f}",fitzpatrick_scale:!1,category:"animals_and_nature"},dizzy:{keywords:["star","sparkle","shoot","magic"],char:"\u{1f4ab}",fitzpatrick_scale:!1,category:"animals_and_nature"},sparkles:{keywords:["stars","shine","shiny","cool","awesome","good","magic"],char:"\u2728",fitzpatrick_scale:!1,category:"animals_and_nature"},comet:{keywords:["space"],char:"\u2604",fitzpatrick_scale:!1,category:"animals_and_nature"},sunny:{keywords:["weather","nature","brightness","summer","beach","spring"],char:"\u2600\ufe0f",fitzpatrick_scale:!1,category:"animals_and_nature"},sun_behind_small_cloud:{keywords:["weather"],char:"\u{1f324}",fitzpatrick_scale:!1,category:"animals_and_nature"},partly_sunny:{keywords:["weather","nature","cloudy","morning","fall","spring"],char:"\u26c5",fitzpatrick_scale:!1,category:"animals_and_nature"},sun_behind_large_cloud:{keywords:["weather"],char:"\u{1f325}",fitzpatrick_scale:!1,category:"animals_and_nature"},sun_behind_rain_cloud:{keywords:["weather"],char:"\u{1f326}",fitzpatrick_scale:!1,category:"animals_and_nature"},cloud:{keywords:["weather","sky"],char:"\u2601\ufe0f",fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_rain:{keywords:["weather"],char:"\u{1f327}",fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_lightning_and_rain:{keywords:["weather","lightning"],char:"\u26c8",fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_lightning:{keywords:["weather","thunder"],char:"\u{1f329}",fitzpatrick_scale:!1,category:"animals_and_nature"},zap:{keywords:["thunder","weather","lightning bolt","fast"],char:"\u26a1",fitzpatrick_scale:!1,category:"animals_and_nature"},fire:{keywords:["hot","cook","flame"],char:"\u{1f525}",fitzpatrick_scale:!1,category:"animals_and_nature"},boom:{keywords:["bomb","explode","explosion","collision","blown"],char:"\u{1f4a5}",fitzpatrick_scale:!1,category:"animals_and_nature"},snowflake:{keywords:["winter","season","cold","weather","christmas","xmas"],char:"\u2744\ufe0f",fitzpatrick_scale:!1,category:"animals_and_nature"},cloud_with_snow:{keywords:["weather"],char:"\u{1f328}",fitzpatrick_scale:!1,category:"animals_and_nature"},snowman:{keywords:["winter","season","cold","weather","christmas","xmas","frozen","without_snow"],char:"\u26c4",fitzpatrick_scale:!1,category:"animals_and_nature"},snowman_with_snow:{keywords:["winter","season","cold","weather","christmas","xmas","frozen"],char:"\u2603",fitzpatrick_scale:!1,category:"animals_and_nature"},wind_face:{keywords:["gust","air"],char:"\u{1f32c}",fitzpatrick_scale:!1,category:"animals_and_nature"},dash:{keywords:["wind","air","fast","shoo","fart","smoke","puff"],char:"\u{1f4a8}",fitzpatrick_scale:!1,category:"animals_and_nature"},tornado:{keywords:["weather","cyclone","twister"],char:"\u{1f32a}",fitzpatrick_scale:!1,category:"animals_and_nature"},fog:{keywords:["weather"],char:"\u{1f32b}",fitzpatrick_scale:!1,category:"animals_and_nature"},open_umbrella:{keywords:["weather","spring"],char:"\u2602",fitzpatrick_scale:!1,category:"animals_and_nature"},umbrella:{keywords:["rainy","weather","spring"],char:"\u2614",fitzpatrick_scale:!1,category:"animals_and_nature"},droplet:{keywords:["water","drip","faucet","spring"],char:"\u{1f4a7}",fitzpatrick_scale:!1,category:"animals_and_nature"},sweat_drops:{keywords:["water","drip","oops"],char:"\u{1f4a6}",fitzpatrick_scale:!1,category:"animals_and_nature"},ocean:{keywords:["sea","water","wave","nature","tsunami","disaster"],char:"\u{1f30a}",fitzpatrick_scale:!1,category:"animals_and_nature"},green_apple:{keywords:["fruit","nature"],char:"\u{1f34f}",fitzpatrick_scale:!1,category:"food_and_drink"},apple:{keywords:["fruit","mac","school"],char:"\u{1f34e}",fitzpatrick_scale:!1,category:"food_and_drink"},pear:{keywords:["fruit","nature","food"],char:"\u{1f350}",fitzpatrick_scale:!1,category:"food_and_drink"},tangerine:{keywords:["food","fruit","nature","orange"],char:"\u{1f34a}",fitzpatrick_scale:!1,category:"food_and_drink"},lemon:{keywords:["fruit","nature"],char:"\u{1f34b}",fitzpatrick_scale:!1,category:"food_and_drink"},banana:{keywords:["fruit","food","monkey"],char:"\u{1f34c}",fitzpatrick_scale:!1,category:"food_and_drink"},watermelon:{keywords:["fruit","food","picnic","summer"],char:"\u{1f349}",fitzpatrick_scale:!1,category:"food_and_drink"},grapes:{keywords:["fruit","food","wine"],char:"\u{1f347}",fitzpatrick_scale:!1,category:"food_and_drink"},strawberry:{keywords:["fruit","food","nature"],char:"\u{1f353}",fitzpatrick_scale:!1,category:"food_and_drink"},melon:{keywords:["fruit","nature","food"],char:"\u{1f348}",fitzpatrick_scale:!1,category:"food_and_drink"},cherries:{keywords:["food","fruit"],char:"\u{1f352}",fitzpatrick_scale:!1,category:"food_and_drink"},peach:{keywords:["fruit","nature","food"],char:"\u{1f351}",fitzpatrick_scale:!1,category:"food_and_drink"},pineapple:{keywords:["fruit","nature","food"],char:"\u{1f34d}",fitzpatrick_scale:!1,category:"food_and_drink"},coconut:{keywords:["fruit","nature","food","palm"],char:"\u{1f965}",fitzpatrick_scale:!1,category:"food_and_drink"},kiwi_fruit:{keywords:["fruit","food"],char:"\u{1f95d}",fitzpatrick_scale:!1,category:"food_and_drink"},mango:{keywords:["fruit","food","tropical"],char:"\u{1f96d}",fitzpatrick_scale:!1,category:"food_and_drink"},avocado:{keywords:["fruit","food"],char:"\u{1f951}",fitzpatrick_scale:!1,category:"food_and_drink"},broccoli:{keywords:["fruit","food","vegetable"],char:"\u{1f966}",fitzpatrick_scale:!1,category:"food_and_drink"},tomato:{keywords:["fruit","vegetable","nature","food"],char:"\u{1f345}",fitzpatrick_scale:!1,category:"food_and_drink"},eggplant:{keywords:["vegetable","nature","food","aubergine"],char:"\u{1f346}",fitzpatrick_scale:!1,category:"food_and_drink"},cucumber:{keywords:["fruit","food","pickle"],char:"\u{1f952}",fitzpatrick_scale:!1,category:"food_and_drink"},carrot:{keywords:["vegetable","food","orange"],char:"\u{1f955}",fitzpatrick_scale:!1,category:"food_and_drink"},hot_pepper:{keywords:["food","spicy","chilli","chili"],char:"\u{1f336}",fitzpatrick_scale:!1,category:"food_and_drink"},potato:{keywords:["food","tuber","vegatable","starch"],char:"\u{1f954}",fitzpatrick_scale:!1,category:"food_and_drink"},corn:{keywords:["food","vegetable","plant"],char:"\u{1f33d}",fitzpatrick_scale:!1,category:"food_and_drink"},leafy_greens:{keywords:["food","vegetable","plant","bok choy","cabbage","kale","lettuce"],char:"\u{1f96c}",fitzpatrick_scale:!1,category:"food_and_drink"},sweet_potato:{keywords:["food","nature"],char:"\u{1f360}",fitzpatrick_scale:!1,category:"food_and_drink"},peanuts:{keywords:["food","nut"],char:"\u{1f95c}",fitzpatrick_scale:!1,category:"food_and_drink"},honey_pot:{keywords:["bees","sweet","kitchen"],char:"\u{1f36f}",fitzpatrick_scale:!1,category:"food_and_drink"},croissant:{keywords:["food","bread","french"],char:"\u{1f950}",fitzpatrick_scale:!1,category:"food_and_drink"},bread:{keywords:["food","wheat","breakfast","toast"],char:"\u{1f35e}",fitzpatrick_scale:!1,category:"food_and_drink"},baguette_bread:{keywords:["food","bread","french"],char:"\u{1f956}",fitzpatrick_scale:!1,category:"food_and_drink"},bagel:{keywords:["food","bread","bakery","schmear"],char:"\u{1f96f}",fitzpatrick_scale:!1,category:"food_and_drink"},pretzel:{keywords:["food","bread","twisted"],char:"\u{1f968}",fitzpatrick_scale:!1,category:"food_and_drink"},cheese:{keywords:["food","chadder"],char:"\u{1f9c0}",fitzpatrick_scale:!1,category:"food_and_drink"},egg:{keywords:["food","chicken","breakfast"],char:"\u{1f95a}",fitzpatrick_scale:!1,category:"food_and_drink"},bacon:{keywords:["food","breakfast","pork","pig","meat"],char:"\u{1f953}",fitzpatrick_scale:!1,category:"food_and_drink"},steak:{keywords:["food","cow","meat","cut","chop","lambchop","porkchop"],char:"\u{1f969}",fitzpatrick_scale:!1,category:"food_and_drink"},pancakes:{keywords:["food","breakfast","flapjacks","hotcakes"],char:"\u{1f95e}",fitzpatrick_scale:!1,category:"food_and_drink"},poultry_leg:{keywords:["food","meat","drumstick","bird","chicken","turkey"],char:"\u{1f357}",fitzpatrick_scale:!1,category:"food_and_drink"},meat_on_bone:{keywords:["good","food","drumstick"],char:"\u{1f356}",fitzpatrick_scale:!1,category:"food_and_drink"},bone:{keywords:["skeleton"],char:"\u{1f9b4}",fitzpatrick_scale:!1,category:"food_and_drink"},fried_shrimp:{keywords:["food","animal","appetizer","summer"],char:"\u{1f364}",fitzpatrick_scale:!1,category:"food_and_drink"},fried_egg:{keywords:["food","breakfast","kitchen","egg"],char:"\u{1f373}",fitzpatrick_scale:!1,category:"food_and_drink"},hamburger:{keywords:["meat","fast food","beef","cheeseburger","mcdonalds","burger king"],char:"\u{1f354}",fitzpatrick_scale:!1,category:"food_and_drink"},fries:{keywords:["chips","snack","fast food"],char:"\u{1f35f}",fitzpatrick_scale:!1,category:"food_and_drink"},stuffed_flatbread:{keywords:["food","flatbread","stuffed","gyro"],char:"\u{1f959}",fitzpatrick_scale:!1,category:"food_and_drink"},hotdog:{keywords:["food","frankfurter"],char:"\u{1f32d}",fitzpatrick_scale:!1,category:"food_and_drink"},pizza:{keywords:["food","party"],char:"\u{1f355}",fitzpatrick_scale:!1,category:"food_and_drink"},sandwich:{keywords:["food","lunch","bread"],char:"\u{1f96a}",fitzpatrick_scale:!1,category:"food_and_drink"},canned_food:{keywords:["food","soup"],char:"\u{1f96b}",fitzpatrick_scale:!1,category:"food_and_drink"},spaghetti:{keywords:["food","italian","noodle"],char:"\u{1f35d}",fitzpatrick_scale:!1,category:"food_and_drink"},taco:{keywords:["food","mexican"],char:"\u{1f32e}",fitzpatrick_scale:!1,category:"food_and_drink"},burrito:{keywords:["food","mexican"],char:"\u{1f32f}",fitzpatrick_scale:!1,category:"food_and_drink"},green_salad:{keywords:["food","healthy","lettuce"],char:"\u{1f957}",fitzpatrick_scale:!1,category:"food_and_drink"},shallow_pan_of_food:{keywords:["food","cooking","casserole","paella"],char:"\u{1f958}",fitzpatrick_scale:!1,category:"food_and_drink"},ramen:{keywords:["food","japanese","noodle","chopsticks"],char:"\u{1f35c}",fitzpatrick_scale:!1,category:"food_and_drink"},stew:{keywords:["food","meat","soup"],char:"\u{1f372}",fitzpatrick_scale:!1,category:"food_and_drink"},fish_cake:{keywords:["food","japan","sea","beach","narutomaki","pink","swirl","kamaboko","surimi","ramen"],char:"\u{1f365}",fitzpatrick_scale:!1,category:"food_and_drink"},fortune_cookie:{keywords:["food","prophecy"],char:"\u{1f960}",fitzpatrick_scale:!1,category:"food_and_drink"},sushi:{keywords:["food","fish","japanese","rice"],char:"\u{1f363}",fitzpatrick_scale:!1,category:"food_and_drink"},bento:{keywords:["food","japanese","box"],char:"\u{1f371}",fitzpatrick_scale:!1,category:"food_and_drink"},curry:{keywords:["food","spicy","hot","indian"],char:"\u{1f35b}",fitzpatrick_scale:!1,category:"food_and_drink"},rice_ball:{keywords:["food","japanese"],char:"\u{1f359}",fitzpatrick_scale:!1,category:"food_and_drink"},rice:{keywords:["food","china","asian"],char:"\u{1f35a}",fitzpatrick_scale:!1,category:"food_and_drink"},rice_cracker:{keywords:["food","japanese"],char:"\u{1f358}",fitzpatrick_scale:!1,category:"food_and_drink"},oden:{keywords:["food","japanese"],char:"\u{1f362}",fitzpatrick_scale:!1,category:"food_and_drink"},dango:{keywords:["food","dessert","sweet","japanese","barbecue","meat"],char:"\u{1f361}",fitzpatrick_scale:!1,category:"food_and_drink"},shaved_ice:{keywords:["hot","dessert","summer"],char:"\u{1f367}",fitzpatrick_scale:!1,category:"food_and_drink"},ice_cream:{keywords:["food","hot","dessert"],char:"\u{1f368}",fitzpatrick_scale:!1,category:"food_and_drink"},icecream:{keywords:["food","hot","dessert","summer"],char:"\u{1f366}",fitzpatrick_scale:!1,category:"food_and_drink"},pie:{keywords:["food","dessert","pastry"],char:"\u{1f967}",fitzpatrick_scale:!1,category:"food_and_drink"},cake:{keywords:["food","dessert"],char:"\u{1f370}",fitzpatrick_scale:!1,category:"food_and_drink"},cupcake:{keywords:["food","dessert","bakery","sweet"],char:"\u{1f9c1}",fitzpatrick_scale:!1,category:"food_and_drink"},moon_cake:{keywords:["food","autumn"],char:"\u{1f96e}",fitzpatrick_scale:!1,category:"food_and_drink"},birthday:{keywords:["food","dessert","cake"],char:"\u{1f382}",fitzpatrick_scale:!1,category:"food_and_drink"},custard:{keywords:["dessert","food"],char:"\u{1f36e}",fitzpatrick_scale:!1,category:"food_and_drink"},candy:{keywords:["snack","dessert","sweet","lolly"],char:"\u{1f36c}",fitzpatrick_scale:!1,category:"food_and_drink"},lollipop:{keywords:["food","snack","candy","sweet"],char:"\u{1f36d}",fitzpatrick_scale:!1,category:"food_and_drink"},chocolate_bar:{keywords:["food","snack","dessert","sweet"],char:"\u{1f36b}",fitzpatrick_scale:!1,category:"food_and_drink"},popcorn:{keywords:["food","movie theater","films","snack"],char:"\u{1f37f}",fitzpatrick_scale:!1,category:"food_and_drink"},dumpling:{keywords:["food","empanada","pierogi","potsticker"],char:"\u{1f95f}",fitzpatrick_scale:!1,category:"food_and_drink"},doughnut:{keywords:["food","dessert","snack","sweet","donut"],char:"\u{1f369}",fitzpatrick_scale:!1,category:"food_and_drink"},cookie:{keywords:["food","snack","oreo","chocolate","sweet","dessert"],char:"\u{1f36a}",fitzpatrick_scale:!1,category:"food_and_drink"},milk_glass:{keywords:["beverage","drink","cow"],char:"\u{1f95b}",fitzpatrick_scale:!1,category:"food_and_drink"},beer:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:"\u{1f37a}",fitzpatrick_scale:!1,category:"food_and_drink"},beers:{keywords:["relax","beverage","drink","drunk","party","pub","summer","alcohol","booze"],char:"\u{1f37b}",fitzpatrick_scale:!1,category:"food_and_drink"},clinking_glasses:{keywords:["beverage","drink","party","alcohol","celebrate","cheers","wine","champagne","toast"],char:"\u{1f942}",fitzpatrick_scale:!1,category:"food_and_drink"},wine_glass:{keywords:["drink","beverage","drunk","alcohol","booze"],char:"\u{1f377}",fitzpatrick_scale:!1,category:"food_and_drink"},tumbler_glass:{keywords:["drink","beverage","drunk","alcohol","liquor","booze","bourbon","scotch","whisky","glass","shot"],char:"\u{1f943}",fitzpatrick_scale:!1,category:"food_and_drink"},cocktail:{keywords:["drink","drunk","alcohol","beverage","booze","mojito"],char:"\u{1f378}",fitzpatrick_scale:!1,category:"food_and_drink"},tropical_drink:{keywords:["beverage","cocktail","summer","beach","alcohol","booze","mojito"],char:"\u{1f379}",fitzpatrick_scale:!1,category:"food_and_drink"},champagne:{keywords:["drink","wine","bottle","celebration"],char:"\u{1f37e}",fitzpatrick_scale:!1,category:"food_and_drink"},sake:{keywords:["wine","drink","drunk","beverage","japanese","alcohol","booze"],char:"\u{1f376}",fitzpatrick_scale:!1,category:"food_and_drink"},tea:{keywords:["drink","bowl","breakfast","green","british"],char:"\u{1f375}",fitzpatrick_scale:!1,category:"food_and_drink"},cup_with_straw:{keywords:["drink","soda"],char:"\u{1f964}",fitzpatrick_scale:!1,category:"food_and_drink"},coffee:{keywords:["beverage","caffeine","latte","espresso"],char:"\u2615",fitzpatrick_scale:!1,category:"food_and_drink"},baby_bottle:{keywords:["food","container","milk"],char:"\u{1f37c}",fitzpatrick_scale:!1,category:"food_and_drink"},salt:{keywords:["condiment","shaker"],char:"\u{1f9c2}",fitzpatrick_scale:!1,category:"food_and_drink"},spoon:{keywords:["cutlery","kitchen","tableware"],char:"\u{1f944}",fitzpatrick_scale:!1,category:"food_and_drink"},fork_and_knife:{keywords:["cutlery","kitchen"],char:"\u{1f374}",fitzpatrick_scale:!1,category:"food_and_drink"},plate_with_cutlery:{keywords:["food","eat","meal","lunch","dinner","restaurant"],char:"\u{1f37d}",fitzpatrick_scale:!1,category:"food_and_drink"},bowl_with_spoon:{keywords:["food","breakfast","cereal","oatmeal","porridge"],char:"\u{1f963}",fitzpatrick_scale:!1,category:"food_and_drink"},takeout_box:{keywords:["food","leftovers"],char:"\u{1f961}",fitzpatrick_scale:!1,category:"food_and_drink"},chopsticks:{keywords:["food"],char:"\u{1f962}",fitzpatrick_scale:!1,category:"food_and_drink"},soccer:{keywords:["sports","football"],char:"\u26bd",fitzpatrick_scale:!1,category:"activity"},basketball:{keywords:["sports","balls","NBA"],char:"\u{1f3c0}",fitzpatrick_scale:!1,category:"activity"},football:{keywords:["sports","balls","NFL"],char:"\u{1f3c8}",fitzpatrick_scale:!1,category:"activity"},baseball:{keywords:["sports","balls"],char:"\u26be",fitzpatrick_scale:!1,category:"activity"},softball:{keywords:["sports","balls"],char:"\u{1f94e}",fitzpatrick_scale:!1,category:"activity"},tennis:{keywords:["sports","balls","green"],char:"\u{1f3be}",fitzpatrick_scale:!1,category:"activity"},volleyball:{keywords:["sports","balls"],char:"\u{1f3d0}",fitzpatrick_scale:!1,category:"activity"},rugby_football:{keywords:["sports","team"],char:"\u{1f3c9}",fitzpatrick_scale:!1,category:"activity"},flying_disc:{keywords:["sports","frisbee","ultimate"],char:"\u{1f94f}",fitzpatrick_scale:!1,category:"activity"},"8ball":{keywords:["pool","hobby","game","luck","magic"],char:"\u{1f3b1}",fitzpatrick_scale:!1,category:"activity"},golf:{keywords:["sports","business","flag","hole","summer"],char:"\u26f3",fitzpatrick_scale:!1,category:"activity"},golfing_woman:{keywords:["sports","business","woman","female"],char:"\u{1f3cc}\ufe0f\u200d\u2640\ufe0f",fitzpatrick_scale:!1,category:"activity"},golfing_man:{keywords:["sports","business"],char:"\u{1f3cc}",fitzpatrick_scale:!0,category:"activity"},ping_pong:{keywords:["sports","pingpong"],char:"\u{1f3d3}",fitzpatrick_scale:!1,category:"activity"},badminton:{keywords:["sports"],char:"\u{1f3f8}",fitzpatrick_scale:!1,category:"activity"},goal_net:{keywords:["sports"],char:"\u{1f945}",fitzpatrick_scale:!1,category:"activity"},ice_hockey:{keywords:["sports"],char:"\u{1f3d2}",fitzpatrick_scale:!1,category:"activity"},field_hockey:{keywords:["sports"],char:"\u{1f3d1}",fitzpatrick_scale:!1,category:"activity"},lacrosse:{keywords:["sports","ball","stick"],char:"\u{1f94d}",fitzpatrick_scale:!1,category:"activity"},cricket:{keywords:["sports"],char:"\u{1f3cf}",fitzpatrick_scale:!1,category:"activity"},ski:{keywords:["sports","winter","cold","snow"],char:"\u{1f3bf}",fitzpatrick_scale:!1,category:"activity"},skier:{keywords:["sports","winter","snow"],char:"\u26f7",fitzpatrick_scale:!1,category:"activity"},snowboarder:{keywords:["sports","winter"],char:"\u{1f3c2}",fitzpatrick_scale:!0,category:"activity"},person_fencing:{keywords:["sports","fencing","sword"],char:"\u{1f93a}",fitzpatrick_scale:!1,category:"activity"},women_wrestling:{keywords:["sports","wrestlers"],char:"\u{1f93c}\u200d\u2640\ufe0f",fitzpatrick_scale:!1,category:"activity"},men_wrestling:{keywords:["sports","wrestlers"],char:"\u{1f93c}\u200d\u2642\ufe0f",fitzpatrick_scale:!1,category:"activity"},woman_cartwheeling:{keywords:["gymnastics"],char:"\u{1f938}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},man_cartwheeling:{keywords:["gymnastics"],char:"\u{1f938}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},woman_playing_handball:{keywords:["sports"],char:"\u{1f93e}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},man_playing_handball:{keywords:["sports"],char:"\u{1f93e}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},ice_skate:{keywords:["sports"],char:"\u26f8",fitzpatrick_scale:!1,category:"activity"},curling_stone:{keywords:["sports"],char:"\u{1f94c}",fitzpatrick_scale:!1,category:"activity"},skateboard:{keywords:["board"],char:"\u{1f6f9}",fitzpatrick_scale:!1,category:"activity"},sled:{keywords:["sleigh","luge","toboggan"],char:"\u{1f6f7}",fitzpatrick_scale:!1,category:"activity"},bow_and_arrow:{keywords:["sports"],char:"\u{1f3f9}",fitzpatrick_scale:!1,category:"activity"},fishing_pole_and_fish:{keywords:["food","hobby","summer"],char:"\u{1f3a3}",fitzpatrick_scale:!1,category:"activity"},boxing_glove:{keywords:["sports","fighting"],char:"\u{1f94a}",fitzpatrick_scale:!1,category:"activity"},martial_arts_uniform:{keywords:["judo","karate","taekwondo"],char:"\u{1f94b}",fitzpatrick_scale:!1,category:"activity"},rowing_woman:{keywords:["sports","hobby","water","ship","woman","female"],char:"\u{1f6a3}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},rowing_man:{keywords:["sports","hobby","water","ship"],char:"\u{1f6a3}",fitzpatrick_scale:!0,category:"activity"},climbing_woman:{keywords:["sports","hobby","woman","female","rock"],char:"\u{1f9d7}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},climbing_man:{keywords:["sports","hobby","man","male","rock"],char:"\u{1f9d7}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},swimming_woman:{keywords:["sports","exercise","human","athlete","water","summer","woman","female"],char:"\u{1f3ca}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},swimming_man:{keywords:["sports","exercise","human","athlete","water","summer"],char:"\u{1f3ca}",fitzpatrick_scale:!0,category:"activity"},woman_playing_water_polo:{keywords:["sports","pool"],char:"\u{1f93d}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},man_playing_water_polo:{keywords:["sports","pool"],char:"\u{1f93d}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},woman_in_lotus_position:{keywords:["woman","female","meditation","yoga","serenity","zen","mindfulness"],char:"\u{1f9d8}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},man_in_lotus_position:{keywords:["man","male","meditation","yoga","serenity","zen","mindfulness"],char:"\u{1f9d8}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},surfing_woman:{keywords:["sports","ocean","sea","summer","beach","woman","female"],char:"\u{1f3c4}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},surfing_man:{keywords:["sports","ocean","sea","summer","beach"],char:"\u{1f3c4}",fitzpatrick_scale:!0,category:"activity"},bath:{keywords:["clean","shower","bathroom"],char:"\u{1f6c0}",fitzpatrick_scale:!0,category:"activity"},basketball_woman:{keywords:["sports","human","woman","female"],char:"\u26f9\ufe0f\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},basketball_man:{keywords:["sports","human"],char:"\u26f9",fitzpatrick_scale:!0,category:"activity"},weight_lifting_woman:{keywords:["sports","training","exercise","woman","female"],char:"\u{1f3cb}\ufe0f\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},weight_lifting_man:{keywords:["sports","training","exercise"],char:"\u{1f3cb}",fitzpatrick_scale:!0,category:"activity"},biking_woman:{keywords:["sports","bike","exercise","hipster","woman","female"],char:"\u{1f6b4}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},biking_man:{keywords:["sports","bike","exercise","hipster"],char:"\u{1f6b4}",fitzpatrick_scale:!0,category:"activity"},mountain_biking_woman:{keywords:["transportation","sports","human","race","bike","woman","female"],char:"\u{1f6b5}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},mountain_biking_man:{keywords:["transportation","sports","human","race","bike"],char:"\u{1f6b5}",fitzpatrick_scale:!0,category:"activity"},horse_racing:{keywords:["animal","betting","competition","gambling","luck"],char:"\u{1f3c7}",fitzpatrick_scale:!0,category:"activity"},business_suit_levitating:{keywords:["suit","business","levitate","hover","jump"],char:"\u{1f574}",fitzpatrick_scale:!0,category:"activity"},trophy:{keywords:["win","award","contest","place","ftw","ceremony"],char:"\u{1f3c6}",fitzpatrick_scale:!1,category:"activity"},running_shirt_with_sash:{keywords:["play","pageant"],char:"\u{1f3bd}",fitzpatrick_scale:!1,category:"activity"},medal_sports:{keywords:["award","winning"],char:"\u{1f3c5}",fitzpatrick_scale:!1,category:"activity"},medal_military:{keywords:["award","winning","army"],char:"\u{1f396}",fitzpatrick_scale:!1,category:"activity"},"1st_place_medal":{keywords:["award","winning","first"],char:"\u{1f947}",fitzpatrick_scale:!1,category:"activity"},"2nd_place_medal":{keywords:["award","second"],char:"\u{1f948}",fitzpatrick_scale:!1,category:"activity"},"3rd_place_medal":{keywords:["award","third"],char:"\u{1f949}",fitzpatrick_scale:!1,category:"activity"},reminder_ribbon:{keywords:["sports","cause","support","awareness"],char:"\u{1f397}",fitzpatrick_scale:!1,category:"activity"},rosette:{keywords:["flower","decoration","military"],char:"\u{1f3f5}",fitzpatrick_scale:!1,category:"activity"},ticket:{keywords:["event","concert","pass"],char:"\u{1f3ab}",fitzpatrick_scale:!1,category:"activity"},tickets:{keywords:["sports","concert","entrance"],char:"\u{1f39f}",fitzpatrick_scale:!1,category:"activity"},performing_arts:{keywords:["acting","theater","drama"],char:"\u{1f3ad}",fitzpatrick_scale:!1,category:"activity"},art:{keywords:["design","paint","draw","colors"],char:"\u{1f3a8}",fitzpatrick_scale:!1,category:"activity"},circus_tent:{keywords:["festival","carnival","party"],char:"\u{1f3aa}",fitzpatrick_scale:!1,category:"activity"},woman_juggling:{keywords:["juggle","balance","skill","multitask"],char:"\u{1f939}\u200d\u2640\ufe0f",fitzpatrick_scale:!0,category:"activity"},man_juggling:{keywords:["juggle","balance","skill","multitask"],char:"\u{1f939}\u200d\u2642\ufe0f",fitzpatrick_scale:!0,category:"activity"},microphone:{keywords:["sound","music","PA","sing","talkshow"],char:"\u{1f3a4}",fitzpatrick_scale:!1,category:"activity"},headphones:{keywords:["music","score","gadgets"],char:"\u{1f3a7}",fitzpatrick_scale:!1,category:"activity"},musical_score:{keywords:["treble","clef","compose"],char:"\u{1f3bc}",fitzpatrick_scale:!1,category:"activity"},musical_keyboard:{keywords:["piano","instrument","compose"],char:"\u{1f3b9}",fitzpatrick_scale:!1,category:"activity"},drum:{keywords:["music","instrument","drumsticks","snare"],char:"\u{1f941}",fitzpatrick_scale:!1,category:"activity"},saxophone:{keywords:["music","instrument","jazz","blues"],char:"\u{1f3b7}",fitzpatrick_scale:!1,category:"activity"},trumpet:{keywords:["music","brass"],char:"\u{1f3ba}",fitzpatrick_scale:!1,category:"activity"},guitar:{keywords:["music","instrument"],char:"\u{1f3b8}",fitzpatrick_scale:!1,category:"activity"},violin:{keywords:["music","instrument","orchestra","symphony"],char:"\u{1f3bb}",fitzpatrick_scale:!1,category:"activity"},clapper:{keywords:["movie","film","record"],char:"\u{1f3ac}",fitzpatrick_scale:!1,category:"activity"},video_game:{keywords:["play","console","PS4","controller"],char:"\u{1f3ae}",fitzpatrick_scale:!1,category:"activity"},space_invader:{keywords:["game","arcade","play"],char:"\u{1f47e}",fitzpatrick_scale:!1,category:"activity"},dart:{keywords:["game","play","bar","target","bullseye"],char:"\u{1f3af}",fitzpatrick_scale:!1,category:"activity"},game_die:{keywords:["dice","random","tabletop","play","luck"],char:"\u{1f3b2}",fitzpatrick_scale:!1,category:"activity"},chess_pawn:{keywords:["expendable"],char:"\u265f",fitzpatrick_scale:!1,category:"activity"},slot_machine:{keywords:["bet","gamble","vegas","fruit machine","luck","casino"],char:"\u{1f3b0}",fitzpatrick_scale:!1,category:"activity"},jigsaw:{keywords:["interlocking","puzzle","piece"],char:"\u{1f9e9}",fitzpatrick_scale:!1,category:"activity"},bowling:{keywords:["sports","fun","play"],char:"\u{1f3b3}",fitzpatrick_scale:!1,category:"activity"},red_car:{keywords:["red","transportation","vehicle"],char:"\u{1f697}",fitzpatrick_scale:!1,category:"travel_and_places"},taxi:{keywords:["uber","vehicle","cars","transportation"],char:"\u{1f695}",fitzpatrick_scale:!1,category:"travel_and_places"},blue_car:{keywords:["transportation","vehicle"],char:"\u{1f699}",fitzpatrick_scale:!1,category:"travel_and_places"},bus:{keywords:["car","vehicle","transportation"],char:"\u{1f68c}",fitzpatrick_scale:!1,category:"travel_and_places"},trolleybus:{keywords:["bart","transportation","vehicle"],char:"\u{1f68e}",fitzpatrick_scale:!1,category:"travel_and_places"},racing_car:{keywords:["sports","race","fast","formula","f1"],char:"\u{1f3ce}",fitzpatrick_scale:!1,category:"travel_and_places"},police_car:{keywords:["vehicle","cars","transportation","law","legal","enforcement"],char:"\u{1f693}",fitzpatrick_scale:!1,category:"travel_and_places"},ambulance:{keywords:["health","911","hospital"],char:"\u{1f691}",fitzpatrick_scale:!1,category:"travel_and_places"},fire_engine:{keywords:["transportation","cars","vehicle"],char:"\u{1f692}",fitzpatrick_scale:!1,category:"travel_and_places"},minibus:{keywords:["vehicle","car","transportation"],char:"\u{1f690}",fitzpatrick_scale:!1,category:"travel_and_places"},truck:{keywords:["cars","transportation"],char:"\u{1f69a}",fitzpatrick_scale:!1,category:"travel_and_places"},articulated_lorry:{keywords:["vehicle","cars","transportation","express"],char:"\u{1f69b}",fitzpatrick_scale:!1,category:"travel_and_places"},tractor:{keywords:["vehicle","car","farming","agriculture"],char:"\u{1f69c}",fitzpatrick_scale:!1,category:"travel_and_places"},kick_scooter:{keywords:["vehicle","kick","razor"],char:"\u{1f6f4}",fitzpatrick_scale:!1,category:"travel_and_places"},motorcycle:{keywords:["race","sports","fast"],char:"\u{1f3cd}",fitzpatrick_scale:!1,category:"travel_and_places"},bike:{keywords:["sports","bicycle","exercise","hipster"],char:"\u{1f6b2}",fitzpatrick_scale:!1,category:"travel_and_places"},motor_scooter:{keywords:["vehicle","vespa","sasha"],char:"\u{1f6f5}",fitzpatrick_scale:!1,category:"travel_and_places"},rotating_light:{keywords:["police","ambulance","911","emergency","alert","error","pinged","law","legal"],char:"\u{1f6a8}",fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_police_car:{keywords:["vehicle","law","legal","enforcement","911"],char:"\u{1f694}",fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_bus:{keywords:["vehicle","transportation"],char:"\u{1f68d}",fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_automobile:{keywords:["car","vehicle","transportation"],char:"\u{1f698}",fitzpatrick_scale:!1,category:"travel_and_places"},oncoming_taxi:{keywords:["vehicle","cars","uber"],char:"\u{1f696}",fitzpatrick_scale:!1,category:"travel_and_places"},aerial_tramway:{keywords:["transportation","vehicle","ski"],char:"\u{1f6a1}",fitzpatrick_scale:!1,category:"travel_and_places"},mountain_cableway:{keywords:["transportation","vehicle","ski"],char:"\u{1f6a0}",fitzpatrick_scale:!1,category:"travel_and_places"},suspension_railway:{keywords:["vehicle","transportation"],char:"\u{1f69f}",fitzpatrick_scale:!1,category:"travel_and_places"},railway_car:{keywords:["transportation","vehicle"],char:"\u{1f683}",fitzpatrick_scale:!1,category:"travel_and_places"},train:{keywords:["transportation","vehicle","carriage","public","travel"],char:"\u{1f68b}",fitzpatrick_scale:!1,category:"travel_and_places"},monorail:{keywords:["transportation","vehicle"],char:"\u{1f69d}",fitzpatrick_scale:!1,category:"travel_and_places"},bullettrain_side:{keywords:["transportation","vehicle"],char:"\u{1f684}",fitzpatrick_scale:!1,category:"travel_and_places"},bullettrain_front:{keywords:["transportation","vehicle","speed","fast","public","travel"],char:"\u{1f685}",fitzpatrick_scale:!1,category:"travel_and_places"},light_rail:{keywords:["transportation","vehicle"],char:"\u{1f688}",fitzpatrick_scale:!1,category:"travel_and_places"},mountain_railway:{keywords:["transportation","vehicle"],char:"\u{1f69e}",fitzpatrick_scale:!1,category:"travel_and_places"},steam_locomotive:{keywords:["transportation","vehicle","train"],char:"\u{1f682}",fitzpatrick_scale:!1,category:"travel_and_places"},train2:{keywords:["transportation","vehicle"],char:"\u{1f686}",fitzpatrick_scale:!1,category:"travel_and_places"},metro:{keywords:["transportation","blue-square","mrt","underground","tube"],char:"\u{1f687}",fitzpatrick_scale:!1,category:"travel_and_places"},tram:{keywords:["transportation","vehicle"],char:"\u{1f68a}",fitzpatrick_scale:!1,category:"travel_and_places"},station:{keywords:["transportation","vehicle","public"],char:"\u{1f689}",fitzpatrick_scale:!1,category:"travel_and_places"},flying_saucer:{keywords:["transportation","vehicle","ufo"],char:"\u{1f6f8}",fitzpatrick_scale:!1,category:"travel_and_places"},helicopter:{keywords:["transportation","vehicle","fly"],char:"\u{1f681}",fitzpatrick_scale:!1,category:"travel_and_places"},small_airplane:{keywords:["flight","transportation","fly","vehicle"],char:"\u{1f6e9}",fitzpatrick_scale:!1,category:"travel_and_places"},airplane:{keywords:["vehicle","transportation","flight","fly"],char:"\u2708\ufe0f",fitzpatrick_scale:!1,category:"travel_and_places"},flight_departure:{keywords:["airport","flight","landing"],char:"\u{1f6eb}",fitzpatrick_scale:!1,category:"travel_and_places"},flight_arrival:{keywords:["airport","flight","boarding"],char:"\u{1f6ec}",fitzpatrick_scale:!1,category:"travel_and_places"},sailboat:{keywords:["ship","summer","transportation","water","sailing"],char:"\u26f5",fitzpatrick_scale:!1,category:"travel_and_places"},motor_boat:{keywords:["ship"],char:"\u{1f6e5}",fitzpatrick_scale:!1,category:"travel_and_places"},speedboat:{keywords:["ship","transportation","vehicle","summer"],char:"\u{1f6a4}",fitzpatrick_scale:!1,category:"travel_and_places"},ferry:{keywords:["boat","ship","yacht"],char:"\u26f4",fitzpatrick_scale:!1,category:"travel_and_places"},passenger_ship:{keywords:["yacht","cruise","ferry"],char:"\u{1f6f3}",fitzpatrick_scale:!1,category:"travel_and_places"},rocket:{keywords:["launch","ship","staffmode","NASA","outer space","outer_space","fly"],char:"\u{1f680}",fitzpatrick_scale:!1,category:"travel_and_places"},artificial_satellite:{keywords:["communication","gps","orbit","spaceflight","NASA","ISS"],char:"\u{1f6f0}",fitzpatrick_scale:!1,category:"travel_and_places"},seat:{keywords:["sit","airplane","transport","bus","flight","fly"],char:"\u{1f4ba}",fitzpatrick_scale:!1,category:"travel_and_places"},canoe:{keywords:["boat","paddle","water","ship"],char:"\u{1f6f6}",fitzpatrick_scale:!1,category:"travel_and_places"},anchor:{keywords:["ship","ferry","sea","boat"],char:"\u2693",fitzpatrick_scale:!1,category:"travel_and_places"},construction:{keywords:["wip","progress","caution","warning"],char:"\u{1f6a7}",fitzpatrick_scale:!1,category:"travel_and_places"},fuelpump:{keywords:["gas station","petroleum"],char:"\u26fd",fitzpatrick_scale:!1,category:"travel_and_places"},busstop:{keywords:["transportation","wait"],char:"\u{1f68f}",fitzpatrick_scale:!1,category:"travel_and_places"},vertical_traffic_light:{keywords:["transportation","driving"],char:"\u{1f6a6}",fitzpatrick_scale:!1,category:"travel_and_places"},traffic_light:{keywords:["transportation","signal"],char:"\u{1f6a5}",fitzpatrick_scale:!1,category:"travel_and_places"},checkered_flag:{keywords:["contest","finishline","race","gokart"],char:"\u{1f3c1}",fitzpatrick_scale:!1,category:"travel_and_places"},ship:{keywords:["transportation","titanic","deploy"],char:"\u{1f6a2}",fitzpatrick_scale:!1,category:"travel_and_places"},ferris_wheel:{keywords:["photo","carnival","londoneye"],char:"\u{1f3a1}",fitzpatrick_scale:!1,category:"travel_and_places"},roller_coaster:{keywords:["carnival","playground","photo","fun"],char:"\u{1f3a2}",fitzpatrick_scale:!1,category:"travel_and_places"},carousel_horse:{keywords:["photo","carnival"],char:"\u{1f3a0}",fitzpatrick_scale:!1,category:"travel_and_places"},building_construction:{keywords:["wip","working","progress"],char:"\u{1f3d7}",fitzpatrick_scale:!1,category:"travel_and_places"},foggy:{keywords:["photo","mountain"],char:"\u{1f301}",fitzpatrick_scale:!1,category:"travel_and_places"},tokyo_tower:{keywords:["photo","japanese"],char:"\u{1f5fc}",fitzpatrick_scale:!1,category:"travel_and_places"},factory:{keywords:["building","industry","pollution","smoke"],char:"\u{1f3ed}",fitzpatrick_scale:!1,category:"travel_and_places"},fountain:{keywords:["photo","summer","water","fresh"],char:"\u26f2",fitzpatrick_scale:!1,category:"travel_and_places"},rice_scene:{keywords:["photo","japan","asia","tsukimi"],char:"\u{1f391}",fitzpatrick_scale:!1,category:"travel_and_places"},mountain:{keywords:["photo","nature","environment"],char:"\u26f0",fitzpatrick_scale:!1,category:"travel_and_places"},mountain_snow:{keywords:["photo","nature","environment","winter","cold"],char:"\u{1f3d4}",fitzpatrick_scale:!1,category:"travel_and_places"},mount_fuji:{keywords:["photo","mountain","nature","japanese"],char:"\u{1f5fb}",fitzpatrick_scale:!1,category:"travel_and_places"},volcano:{keywords:["photo","nature","disaster"],char:"\u{1f30b}",fitzpatrick_scale:!1,category:"travel_and_places"},japan:{keywords:["nation","country","japanese","asia"],char:"\u{1f5fe}",fitzpatrick_scale:!1,category:"travel_and_places"},camping:{keywords:["photo","outdoors","tent"],char:"\u{1f3d5}",fitzpatrick_scale:!1,category:"travel_and_places"},tent:{keywords:["photo","camping","outdoors"],char:"\u26fa",fitzpatrick_scale:!1,category:"travel_and_places"},national_park:{keywords:["photo","environment","nature"],char:"\u{1f3de}",fitzpatrick_scale:!1,category:"travel_and_places"},motorway:{keywords:["road","cupertino","interstate","highway"],char:"\u{1f6e3}",fitzpatrick_scale:!1,category:"travel_and_places"},railway_track:{keywords:["train","transportation"],char:"\u{1f6e4}",fitzpatrick_scale:!1,category:"travel_and_places"},sunrise:{keywords:["morning","view","vacation","photo"],char:"\u{1f305}",fitzpatrick_scale:!1,category:"travel_and_places"},sunrise_over_mountains:{keywords:["view","vacation","photo"],char:"\u{1f304}",fitzpatrick_scale:!1,category:"travel_and_places"},desert:{keywords:["photo","warm","saharah"],char:"\u{1f3dc}",fitzpatrick_scale:!1,category:"travel_and_places"},beach_umbrella:{keywords:["weather","summer","sunny","sand","mojito"],char:"\u{1f3d6}",fitzpatrick_scale:!1,category:"travel_and_places"},desert_island:{keywords:["photo","tropical","mojito"],char:"\u{1f3dd}",fitzpatrick_scale:!1,category:"travel_and_places"},city_sunrise:{keywords:["photo","good morning","dawn"],char:"\u{1f307}",fitzpatrick_scale:!1,category:"travel_and_places"},city_sunset:{keywords:["photo","evening","sky","buildings"],char:"\u{1f306}",fitzpatrick_scale:!1,category:"travel_and_places"},cityscape:{keywords:["photo","night life","urban"],char:"\u{1f3d9}",fitzpatrick_scale:!1,category:"travel_and_places"},night_with_stars:{keywords:["evening","city","downtown"],char:"\u{1f303}",fitzpatrick_scale:!1,category:"travel_and_places"},bridge_at_night:{keywords:["photo","sanfrancisco"],char:"\u{1f309}",fitzpatrick_scale:!1,category:"travel_and_places"},milky_way:{keywords:["photo","space","stars"],char:"\u{1f30c}",fitzpatrick_scale:!1,category:"travel_and_places"},stars:{keywords:["night","photo"],char:"\u{1f320}",fitzpatrick_scale:!1,category:"travel_and_places"},sparkler:{keywords:["stars","night","shine"],char:"\u{1f387}",fitzpatrick_scale:!1,category:"travel_and_places"},fireworks:{keywords:["photo","festival","carnival","congratulations"],char:"\u{1f386}",fitzpatrick_scale:!1,category:"travel_and_places"},rainbow:{keywords:["nature","happy","unicorn_face","photo","sky","spring"],char:"\u{1f308}",fitzpatrick_scale:!1,category:"travel_and_places"},houses:{keywords:["buildings","photo"],char:"\u{1f3d8}",fitzpatrick_scale:!1,category:"travel_and_places"},european_castle:{keywords:["building","royalty","history"],char:"\u{1f3f0}",fitzpatrick_scale:!1,category:"travel_and_places"},japanese_castle:{keywords:["photo","building"],char:"\u{1f3ef}",fitzpatrick_scale:!1,category:"travel_and_places"},stadium:{keywords:["photo","place","sports","concert","venue"],char:"\u{1f3df}",fitzpatrick_scale:!1,category:"travel_and_places"},statue_of_liberty:{keywords:["american","newyork"],char:"\u{1f5fd}",fitzpatrick_scale:!1,category:"travel_and_places"},house:{keywords:["building","home"],char:"\u{1f3e0}",fitzpatrick_scale:!1,category:"travel_and_places"},house_with_garden:{keywords:["home","plant","nature"],char:"\u{1f3e1}",fitzpatrick_scale:!1,category:"travel_and_places"},derelict_house:{keywords:["abandon","evict","broken","building"],char:"\u{1f3da}",fitzpatrick_scale:!1,category:"travel_and_places"},office:{keywords:["building","bureau","work"],char:"\u{1f3e2}",fitzpatrick_scale:!1,category:"travel_and_places"},department_store:{keywords:["building","shopping","mall"],char:"\u{1f3ec}",fitzpatrick_scale:!1,category:"travel_and_places"},post_office:{keywords:["building","envelope","communication"],char:"\u{1f3e3}",fitzpatrick_scale:!1,category:"travel_and_places"},european_post_office:{keywords:["building","email"],char:"\u{1f3e4}",fitzpatrick_scale:!1,category:"travel_and_places"},hospital:{keywords:["building","health","surgery","doctor"],char:"\u{1f3e5}",fitzpatrick_scale:!1,category:"travel_and_places"},bank:{keywords:["building","money","sales","cash","business","enterprise"],char:"\u{1f3e6}",fitzpatrick_scale:!1,category:"travel_and_places"},hotel:{keywords:["building","accomodation","checkin"],char:"\u{1f3e8}",fitzpatrick_scale:!1,category:"travel_and_places"},convenience_store:{keywords:["building","shopping","groceries"],char:"\u{1f3ea}",fitzpatrick_scale:!1,category:"travel_and_places"},school:{keywords:["building","student","education","learn","teach"],char:"\u{1f3eb}",fitzpatrick_scale:!1,category:"travel_and_places"},love_hotel:{keywords:["like","affection","dating"],char:"\u{1f3e9}",fitzpatrick_scale:!1,category:"travel_and_places"},wedding:{keywords:["love","like","affection","couple","marriage","bride","groom"],char:"\u{1f492}",fitzpatrick_scale:!1,category:"travel_and_places"},classical_building:{keywords:["art","culture","history"],char:"\u{1f3db}",fitzpatrick_scale:!1,category:"travel_and_places"},church:{keywords:["building","religion","christ"],char:"\u26ea",fitzpatrick_scale:!1,category:"travel_and_places"},mosque:{keywords:["islam","worship","minaret"],char:"\u{1f54c}",fitzpatrick_scale:!1,category:"travel_and_places"},synagogue:{keywords:["judaism","worship","temple","jewish"],char:"\u{1f54d}",fitzpatrick_scale:!1,category:"travel_and_places"},kaaba:{keywords:["mecca","mosque","islam"],char:"\u{1f54b}",fitzpatrick_scale:!1,category:"travel_and_places"},shinto_shrine:{keywords:["temple","japan","kyoto"],char:"\u26e9",fitzpatrick_scale:!1,category:"travel_and_places"},watch:{keywords:["time","accessories"],char:"\u231a",fitzpatrick_scale:!1,category:"objects"},iphone:{keywords:["technology","apple","gadgets","dial"],char:"\u{1f4f1}",fitzpatrick_scale:!1,category:"objects"},calling:{keywords:["iphone","incoming"],char:"\u{1f4f2}",fitzpatrick_scale:!1,category:"objects"},computer:{keywords:["technology","laptop","screen","display","monitor"],char:"\u{1f4bb}",fitzpatrick_scale:!1,category:"objects"},keyboard:{keywords:["technology","computer","type","input","text"],char:"\u2328",fitzpatrick_scale:!1,category:"objects"},desktop_computer:{keywords:["technology","computing","screen"],char:"\u{1f5a5}",fitzpatrick_scale:!1,category:"objects"},printer:{keywords:["paper","ink"],char:"\u{1f5a8}",fitzpatrick_scale:!1,category:"objects"},computer_mouse:{keywords:["click"],char:"\u{1f5b1}",fitzpatrick_scale:!1,category:"objects"},trackball:{keywords:["technology","trackpad"],char:"\u{1f5b2}",fitzpatrick_scale:!1,category:"objects"},joystick:{keywords:["game","play"],char:"\u{1f579}",fitzpatrick_scale:!1,category:"objects"},clamp:{keywords:["tool"],char:"\u{1f5dc}",fitzpatrick_scale:!1,category:"objects"},minidisc:{keywords:["technology","record","data","disk","90s"],char:"\u{1f4bd}",fitzpatrick_scale:!1,category:"objects"},floppy_disk:{keywords:["oldschool","technology","save","90s","80s"],char:"\u{1f4be}",fitzpatrick_scale:!1,category:"objects"},cd:{keywords:["technology","dvd","disk","disc","90s"],char:"\u{1f4bf}",fitzpatrick_scale:!1,category:"objects"},dvd:{keywords:["cd","disk","disc"],char:"\u{1f4c0}",fitzpatrick_scale:!1,category:"objects"},vhs:{keywords:["record","video","oldschool","90s","80s"],char:"\u{1f4fc}",fitzpatrick_scale:!1,category:"objects"},camera:{keywords:["gadgets","photography"],char:"\u{1f4f7}",fitzpatrick_scale:!1,category:"objects"},camera_flash:{keywords:["photography","gadgets"],char:"\u{1f4f8}",fitzpatrick_scale:!1,category:"objects"},video_camera:{keywords:["film","record"],char:"\u{1f4f9}",fitzpatrick_scale:!1,category:"objects"},movie_camera:{keywords:["film","record"],char:"\u{1f3a5}",fitzpatrick_scale:!1,category:"objects"},film_projector:{keywords:["video","tape","record","movie"],char:"\u{1f4fd}",fitzpatrick_scale:!1,category:"objects"},film_strip:{keywords:["movie"],char:"\u{1f39e}",fitzpatrick_scale:!1,category:"objects"},telephone_receiver:{keywords:["technology","communication","dial"],char:"\u{1f4de}",fitzpatrick_scale:!1,category:"objects"},phone:{keywords:["technology","communication","dial","telephone"],char:"\u260e\ufe0f",fitzpatrick_scale:!1,category:"objects"},pager:{keywords:["bbcall","oldschool","90s"],char:"\u{1f4df}",fitzpatrick_scale:!1,category:"objects"},fax:{keywords:["communication","technology"],char:"\u{1f4e0}",fitzpatrick_scale:!1,category:"objects"},tv:{keywords:["technology","program","oldschool","show","television"],char:"\u{1f4fa}",fitzpatrick_scale:!1,category:"objects"},radio:{keywords:["communication","music","podcast","program"],char:"\u{1f4fb}",fitzpatrick_scale:!1,category:"objects"},studio_microphone:{keywords:["sing","recording","artist","talkshow"],char:"\u{1f399}",fitzpatrick_scale:!1,category:"objects"},level_slider:{keywords:["scale"],char:"\u{1f39a}",fitzpatrick_scale:!1,category:"objects"},control_knobs:{keywords:["dial"],char:"\u{1f39b}",fitzpatrick_scale:!1,category:"objects"},compass:{keywords:["magnetic","navigation","orienteering"],char:"\u{1f9ed}",fitzpatrick_scale:!1,category:"objects"},stopwatch:{keywords:["time","deadline"],char:"\u23f1",fitzpatrick_scale:!1,category:"objects"},timer_clock:{keywords:["alarm"],char:"\u23f2",fitzpatrick_scale:!1,category:"objects"},alarm_clock:{keywords:["time","wake"],char:"\u23f0",fitzpatrick_scale:!1,category:"objects"},mantelpiece_clock:{keywords:["time"],char:"\u{1f570}",fitzpatrick_scale:!1,category:"objects"},hourglass_flowing_sand:{keywords:["oldschool","time","countdown"],char:"\u23f3",fitzpatrick_scale:!1,category:"objects"},hourglass:{keywords:["time","clock","oldschool","limit","exam","quiz","test"],char:"\u231b",fitzpatrick_scale:!1,category:"objects"},satellite:{keywords:["communication","future","radio","space"],char:"\u{1f4e1}",fitzpatrick_scale:!1,category:"objects"},battery:{keywords:["power","energy","sustain"],char:"\u{1f50b}",fitzpatrick_scale:!1,category:"objects"},electric_plug:{keywords:["charger","power"],char:"\u{1f50c}",fitzpatrick_scale:!1,category:"objects"},bulb:{keywords:["light","electricity","idea"],char:"\u{1f4a1}",fitzpatrick_scale:!1,category:"objects"},flashlight:{keywords:["dark","camping","sight","night"],char:"\u{1f526}",fitzpatrick_scale:!1,category:"objects"},candle:{keywords:["fire","wax"],char:"\u{1f56f}",fitzpatrick_scale:!1,category:"objects"},fire_extinguisher:{keywords:["quench"],char:"\u{1f9ef}",fitzpatrick_scale:!1,category:"objects"},wastebasket:{keywords:["bin","trash","rubbish","garbage","toss"],char:"\u{1f5d1}",fitzpatrick_scale:!1,category:"objects"},oil_drum:{keywords:["barrell"],char:"\u{1f6e2}",fitzpatrick_scale:!1,category:"objects"},money_with_wings:{keywords:["dollar","bills","payment","sale"],char:"\u{1f4b8}",fitzpatrick_scale:!1,category:"objects"},dollar:{keywords:["money","sales","bill","currency"],char:"\u{1f4b5}",fitzpatrick_scale:!1,category:"objects"},yen:{keywords:["money","sales","japanese","dollar","currency"],char:"\u{1f4b4}",fitzpatrick_scale:!1,category:"objects"},euro:{keywords:["money","sales","dollar","currency"],char:"\u{1f4b6}",fitzpatrick_scale:!1,category:"objects"},pound:{keywords:["british","sterling","money","sales","bills","uk","england","currency"],char:"\u{1f4b7}",fitzpatrick_scale:!1,category:"objects"},moneybag:{keywords:["dollar","payment","coins","sale"],char:"\u{1f4b0}",fitzpatrick_scale:!1,category:"objects"},credit_card:{keywords:["money","sales","dollar","bill","payment","shopping"],char:"\u{1f4b3}",fitzpatrick_scale:!1,category:"objects"},gem:{keywords:["blue","ruby","diamond","jewelry"],char:"\u{1f48e}",fitzpatrick_scale:!1,category:"objects"},balance_scale:{keywords:["law","fairness","weight"],char:"\u2696",fitzpatrick_scale:!1,category:"objects"},toolbox:{keywords:["tools","diy","fix","maintainer","mechanic"],char:"\u{1f9f0}",fitzpatrick_scale:!1,category:"objects"},wrench:{keywords:["tools","diy","ikea","fix","maintainer"],char:"\u{1f527}",fitzpatrick_scale:!1,category:"objects"},hammer:{keywords:["tools","build","create"],char:"\u{1f528}",fitzpatrick_scale:!1,category:"objects"},hammer_and_pick:{keywords:["tools","build","create"],char:"\u2692",fitzpatrick_scale:!1,category:"objects"},hammer_and_wrench:{keywords:["tools","build","create"],char:"\u{1f6e0}",fitzpatrick_scale:!1,category:"objects"},pick:{keywords:["tools","dig"],char:"\u26cf",fitzpatrick_scale:!1,category:"objects"},nut_and_bolt:{keywords:["handy","tools","fix"],char:"\u{1f529}",fitzpatrick_scale:!1,category:"objects"},gear:{keywords:["cog"],char:"\u2699",fitzpatrick_scale:!1,category:"objects"},brick:{keywords:["bricks"],char:"\u{1f9f1}",fitzpatrick_scale:!1,category:"objects"},chains:{keywords:["lock","arrest"],char:"\u26d3",fitzpatrick_scale:!1,category:"objects"},magnet:{keywords:["attraction","magnetic"],char:"\u{1f9f2}",fitzpatrick_scale:!1,category:"objects"},gun:{keywords:["violence","weapon","pistol","revolver"],char:"\u{1f52b}",fitzpatrick_scale:!1,category:"objects"},bomb:{keywords:["boom","explode","explosion","terrorism"],char:"\u{1f4a3}",fitzpatrick_scale:!1,category:"objects"},firecracker:{keywords:["dynamite","boom","explode","explosion","explosive"],char:"\u{1f9e8}",fitzpatrick_scale:!1,category:"objects"},hocho:{keywords:["knife","blade","cutlery","kitchen","weapon"],char:"\u{1f52a}",fitzpatrick_scale:!1,category:"objects"},dagger:{keywords:["weapon"],char:"\u{1f5e1}",fitzpatrick_scale:!1,category:"objects"},crossed_swords:{keywords:["weapon"],char:"\u2694",fitzpatrick_scale:!1,category:"objects"},shield:{keywords:["protection","security"],char:"\u{1f6e1}",fitzpatrick_scale:!1,category:"objects"},smoking:{keywords:["kills","tobacco","cigarette","joint","smoke"],char:"\u{1f6ac}",fitzpatrick_scale:!1,category:"objects"},skull_and_crossbones:{keywords:["poison","danger","deadly","scary","death","pirate","evil"],char:"\u2620",fitzpatrick_scale:!1,category:"objects"},coffin:{keywords:["vampire","dead","die","death","rip","graveyard","cemetery","casket","funeral","box"],char:"\u26b0",fitzpatrick_scale:!1,category:"objects"},funeral_urn:{keywords:["dead","die","death","rip","ashes"],char:"\u26b1",fitzpatrick_scale:!1,category:"objects"},amphora:{keywords:["vase","jar"],char:"\u{1f3fa}",fitzpatrick_scale:!1,category:"objects"},crystal_ball:{keywords:["disco","party","magic","circus","fortune_teller"],char:"\u{1f52e}",fitzpatrick_scale:!1,category:"objects"},prayer_beads:{keywords:["dhikr","religious"],char:"\u{1f4ff}",fitzpatrick_scale:!1,category:"objects"},nazar_amulet:{keywords:["bead","charm"],char:"\u{1f9ff}",fitzpatrick_scale:!1,category:"objects"},barber:{keywords:["hair","salon","style"],char:"\u{1f488}",fitzpatrick_scale:!1,category:"objects"},alembic:{keywords:["distilling","science","experiment","chemistry"],char:"\u2697",fitzpatrick_scale:!1,category:"objects"},telescope:{keywords:["stars","space","zoom","science","astronomy"],char:"\u{1f52d}",fitzpatrick_scale:!1,category:"objects"},microscope:{keywords:["laboratory","experiment","zoomin","science","study"],char:"\u{1f52c}",fitzpatrick_scale:!1,category:"objects"},hole:{keywords:["embarrassing"],char:"\u{1f573}",fitzpatrick_scale:!1,category:"objects"},pill:{keywords:["health","medicine","doctor","pharmacy","drug"],char:"\u{1f48a}",fitzpatrick_scale:!1,category:"objects"},syringe:{keywords:["health","hospital","drugs","blood","medicine","needle","doctor","nurse"],char:"\u{1f489}",fitzpatrick_scale:!1,category:"objects"},dna:{keywords:["biologist","genetics","life"],char:"\u{1f9ec}",fitzpatrick_scale:!1,category:"objects"},microbe:{keywords:["amoeba","bacteria","germs"],char:"\u{1f9a0}",fitzpatrick_scale:!1,category:"objects"},petri_dish:{keywords:["bacteria","biology","culture","lab"],char:"\u{1f9eb}",fitzpatrick_scale:!1,category:"objects"},test_tube:{keywords:["chemistry","experiment","lab","science"],char:"\u{1f9ea}",fitzpatrick_scale:!1,category:"objects"},thermometer:{keywords:["weather","temperature","hot","cold"],char:"\u{1f321}",fitzpatrick_scale:!1,category:"objects"},broom:{keywords:["cleaning","sweeping","witch"],char:"\u{1f9f9}",fitzpatrick_scale:!1,category:"objects"},basket:{keywords:["laundry"],char:"\u{1f9fa}",fitzpatrick_scale:!1,category:"objects"},toilet_paper:{keywords:["roll"],char:"\u{1f9fb}",fitzpatrick_scale:!1,category:"objects"},label:{keywords:["sale","tag"],char:"\u{1f3f7}",fitzpatrick_scale:!1,category:"objects"},bookmark:{keywords:["favorite","label","save"],char:"\u{1f516}",fitzpatrick_scale:!1,category:"objects"},toilet:{keywords:["restroom","wc","washroom","bathroom","potty"],char:"\u{1f6bd}",fitzpatrick_scale:!1,category:"objects"},shower:{keywords:["clean","water","bathroom"],char:"\u{1f6bf}",fitzpatrick_scale:!1,category:"objects"},bathtub:{keywords:["clean","shower","bathroom"],char:"\u{1f6c1}",fitzpatrick_scale:!1,category:"objects"},soap:{keywords:["bar","bathing","cleaning","lather"],char:"\u{1f9fc}",fitzpatrick_scale:!1,category:"objects"},sponge:{keywords:["absorbing","cleaning","porous"],char:"\u{1f9fd}",fitzpatrick_scale:!1,category:"objects"},lotion_bottle:{keywords:["moisturizer","sunscreen"],char:"\u{1f9f4}",fitzpatrick_scale:!1,category:"objects"},key:{keywords:["lock","door","password"],char:"\u{1f511}",fitzpatrick_scale:!1,category:"objects"},old_key:{keywords:["lock","door","password"],char:"\u{1f5dd}",fitzpatrick_scale:!1,category:"objects"},couch_and_lamp:{keywords:["read","chill"],char:"\u{1f6cb}",fitzpatrick_scale:!1,category:"objects"},sleeping_bed:{keywords:["bed","rest"],char:"\u{1f6cc}",fitzpatrick_scale:!0,category:"objects"},bed:{keywords:["sleep","rest"],char:"\u{1f6cf}",fitzpatrick_scale:!1,category:"objects"},door:{keywords:["house","entry","exit"],char:"\u{1f6aa}",fitzpatrick_scale:!1,category:"objects"},bellhop_bell:{keywords:["service"],char:"\u{1f6ce}",fitzpatrick_scale:!1,category:"objects"},teddy_bear:{keywords:["plush","stuffed"],char:"\u{1f9f8}",fitzpatrick_scale:!1,category:"objects"},framed_picture:{keywords:["photography"],char:"\u{1f5bc}",fitzpatrick_scale:!1,category:"objects"},world_map:{keywords:["location","direction"],char:"\u{1f5fa}",fitzpatrick_scale:!1,category:"objects"},parasol_on_ground:{keywords:["weather","summer"],char:"\u26f1",fitzpatrick_scale:!1,category:"objects"},moyai:{keywords:["rock","easter island","moai"],char:"\u{1f5ff}",fitzpatrick_scale:!1,category:"objects"},shopping:{keywords:["mall","buy","purchase"],char:"\u{1f6cd}",fitzpatrick_scale:!1,category:"objects"},shopping_cart:{keywords:["trolley"],char:"\u{1f6d2}",fitzpatrick_scale:!1,category:"objects"},balloon:{keywords:["party","celebration","birthday","circus"],char:"\u{1f388}",fitzpatrick_scale:!1,category:"objects"},flags:{keywords:["fish","japanese","koinobori","carp","banner"],char:"\u{1f38f}",fitzpatrick_scale:!1,category:"objects"},ribbon:{keywords:["decoration","pink","girl","bowtie"],char:"\u{1f380}",fitzpatrick_scale:!1,category:"objects"},gift:{keywords:["present","birthday","christmas","xmas"],char:"\u{1f381}",fitzpatrick_scale:!1,category:"objects"},confetti_ball:{keywords:["festival","party","birthday","circus"],char:"\u{1f38a}",fitzpatrick_scale:!1,category:"objects"},tada:{keywords:["party","congratulations","birthday","magic","circus","celebration"],char:"\u{1f389}",fitzpatrick_scale:!1,category:"objects"},dolls:{keywords:["japanese","toy","kimono"],char:"\u{1f38e}",fitzpatrick_scale:!1,category:"objects"},wind_chime:{keywords:["nature","ding","spring","bell"],char:"\u{1f390}",fitzpatrick_scale:!1,category:"objects"},crossed_flags:{keywords:["japanese","nation","country","border"],char:"\u{1f38c}",fitzpatrick_scale:!1,category:"objects"},izakaya_lantern:{keywords:["light","paper","halloween","spooky"],char:"\u{1f3ee}",fitzpatrick_scale:!1,category:"objects"},red_envelope:{keywords:["gift"],char:"\u{1f9e7}",fitzpatrick_scale:!1,category:"objects"},email:{keywords:["letter","postal","inbox","communication"],char:"\u2709\ufe0f",fitzpatrick_scale:!1,category:"objects"},envelope_with_arrow:{keywords:["email","communication"],char:"\u{1f4e9}",fitzpatrick_scale:!1,category:"objects"},incoming_envelope:{keywords:["email","inbox"],char:"\u{1f4e8}",fitzpatrick_scale:!1,category:"objects"},"e-mail":{keywords:["communication","inbox"],char:"\u{1f4e7}",fitzpatrick_scale:!1,category:"objects"},love_letter:{keywords:["email","like","affection","envelope","valentines"],char:"\u{1f48c}",fitzpatrick_scale:!1,category:"objects"},postbox:{keywords:["email","letter","envelope"],char:"\u{1f4ee}",fitzpatrick_scale:!1,category:"objects"},mailbox_closed:{keywords:["email","communication","inbox"],char:"\u{1f4ea}",fitzpatrick_scale:!1,category:"objects"},mailbox:{keywords:["email","inbox","communication"],char:"\u{1f4eb}",fitzpatrick_scale:!1,category:"objects"},mailbox_with_mail:{keywords:["email","inbox","communication"],char:"\u{1f4ec}",fitzpatrick_scale:!1,category:"objects"},mailbox_with_no_mail:{keywords:["email","inbox"],char:"\u{1f4ed}",fitzpatrick_scale:!1,category:"objects"},package:{keywords:["mail","gift","cardboard","box","moving"],char:"\u{1f4e6}",fitzpatrick_scale:!1,category:"objects"},postal_horn:{keywords:["instrument","music"],char:"\u{1f4ef}",fitzpatrick_scale:!1,category:"objects"},inbox_tray:{keywords:["email","documents"],char:"\u{1f4e5}",fitzpatrick_scale:!1,category:"objects"},outbox_tray:{keywords:["inbox","email"],char:"\u{1f4e4}",fitzpatrick_scale:!1,category:"objects"},scroll:{keywords:["documents","ancient","history","paper"],char:"\u{1f4dc}",fitzpatrick_scale:!1,category:"objects"},page_with_curl:{keywords:["documents","office","paper"],char:"\u{1f4c3}",fitzpatrick_scale:!1,category:"objects"},bookmark_tabs:{keywords:["favorite","save","order","tidy"],char:"\u{1f4d1}",fitzpatrick_scale:!1,category:"objects"},receipt:{keywords:["accounting","expenses"],char:"\u{1f9fe}",fitzpatrick_scale:!1,category:"objects"},bar_chart:{keywords:["graph","presentation","stats"],char:"\u{1f4ca}",fitzpatrick_scale:!1,category:"objects"},chart_with_upwards_trend:{keywords:["graph","presentation","stats","recovery","business","economics","money","sales","good","success"],char:"\u{1f4c8}",fitzpatrick_scale:!1,category:"objects"},chart_with_downwards_trend:{keywords:["graph","presentation","stats","recession","business","economics","money","sales","bad","failure"],char:"\u{1f4c9}",fitzpatrick_scale:!1,category:"objects"},page_facing_up:{keywords:["documents","office","paper","information"],char:"\u{1f4c4}",fitzpatrick_scale:!1,category:"objects"},date:{keywords:["calendar","schedule"],char:"\u{1f4c5}",fitzpatrick_scale:!1,category:"objects"},calendar:{keywords:["schedule","date","planning"],char:"\u{1f4c6}",fitzpatrick_scale:!1,category:"objects"},spiral_calendar:{keywords:["date","schedule","planning"],char:"\u{1f5d3}",fitzpatrick_scale:!1,category:"objects"},card_index:{keywords:["business","stationery"],char:"\u{1f4c7}",fitzpatrick_scale:!1,category:"objects"},card_file_box:{keywords:["business","stationery"],char:"\u{1f5c3}",fitzpatrick_scale:!1,category:"objects"},ballot_box:{keywords:["election","vote"],char:"\u{1f5f3}",fitzpatrick_scale:!1,category:"objects"},file_cabinet:{keywords:["filing","organizing"],char:"\u{1f5c4}",fitzpatrick_scale:!1,category:"objects"},clipboard:{keywords:["stationery","documents"],char:"\u{1f4cb}",fitzpatrick_scale:!1,category:"objects"},spiral_notepad:{keywords:["memo","stationery"],char:"\u{1f5d2}",fitzpatrick_scale:!1,category:"objects"},file_folder:{keywords:["documents","business","office"],char:"\u{1f4c1}",fitzpatrick_scale:!1,category:"objects"},open_file_folder:{keywords:["documents","load"],char:"\u{1f4c2}",fitzpatrick_scale:!1,category:"objects"},card_index_dividers:{keywords:["organizing","business","stationery"],char:"\u{1f5c2}",fitzpatrick_scale:!1,category:"objects"},newspaper_roll:{keywords:["press","headline"],char:"\u{1f5de}",fitzpatrick_scale:!1,category:"objects"},newspaper:{keywords:["press","headline"],char:"\u{1f4f0}",fitzpatrick_scale:!1,category:"objects"},notebook:{keywords:["stationery","record","notes","paper","study"],char:"\u{1f4d3}",fitzpatrick_scale:!1,category:"objects"},closed_book:{keywords:["read","library","knowledge","textbook","learn"],char:"\u{1f4d5}",fitzpatrick_scale:!1,category:"objects"},green_book:{keywords:["read","library","knowledge","study"],char:"\u{1f4d7}",fitzpatrick_scale:!1,category:"objects"},blue_book:{keywords:["read","library","knowledge","learn","study"],char:"\u{1f4d8}",fitzpatrick_scale:!1,category:"objects"},orange_book:{keywords:["read","library","knowledge","textbook","study"],char:"\u{1f4d9}",fitzpatrick_scale:!1,category:"objects"},notebook_with_decorative_cover:{keywords:["classroom","notes","record","paper","study"],char:"\u{1f4d4}",fitzpatrick_scale:!1,category:"objects"},ledger:{keywords:["notes","paper"],char:"\u{1f4d2}",fitzpatrick_scale:!1,category:"objects"},books:{keywords:["literature","library","study"],char:"\u{1f4da}",fitzpatrick_scale:!1,category:"objects"},open_book:{keywords:["book","read","library","knowledge","literature","learn","study"],char:"\u{1f4d6}",fitzpatrick_scale:!1,category:"objects"},safety_pin:{keywords:["diaper"],char:"\u{1f9f7}",fitzpatrick_scale:!1,category:"objects"},link:{keywords:["rings","url"],char:"\u{1f517}",fitzpatrick_scale:!1,category:"objects"},paperclip:{keywords:["documents","stationery"],char:"\u{1f4ce}",fitzpatrick_scale:!1,category:"objects"},paperclips:{keywords:["documents","stationery"],char:"\u{1f587}",fitzpatrick_scale:!1,category:"objects"},scissors:{keywords:["stationery","cut"],char:"\u2702\ufe0f",fitzpatrick_scale:!1,category:"objects"},triangular_ruler:{keywords:["stationery","math","architect","sketch"],char:"\u{1f4d0}",fitzpatrick_scale:!1,category:"objects"},straight_ruler:{keywords:["stationery","calculate","length","math","school","drawing","architect","sketch"],char:"\u{1f4cf}",fitzpatrick_scale:!1,category:"objects"},abacus:{keywords:["calculation"],char:"\u{1f9ee}",fitzpatrick_scale:!1,category:"objects"},pushpin:{keywords:["stationery","mark","here"],char:"\u{1f4cc}",fitzpatrick_scale:!1,category:"objects"},round_pushpin:{keywords:["stationery","location","map","here"],char:"\u{1f4cd}",fitzpatrick_scale:!1,category:"objects"},triangular_flag_on_post:{keywords:["mark","milestone","place"],char:"\u{1f6a9}",fitzpatrick_scale:!1,category:"objects"},white_flag:{keywords:["losing","loser","lost","surrender","give up","fail"],char:"\u{1f3f3}",fitzpatrick_scale:!1,category:"objects"},black_flag:{keywords:["pirate"],char:"\u{1f3f4}",fitzpatrick_scale:!1,category:"objects"},rainbow_flag:{keywords:["flag","rainbow","pride","gay","lgbt","glbt","queer","homosexual","lesbian","bisexual","transgender"],char:"\u{1f3f3}\ufe0f\u200d\u{1f308}",fitzpatrick_scale:!1,category:"objects"},closed_lock_with_key:{keywords:["security","privacy"],char:"\u{1f510}",fitzpatrick_scale:!1,category:"objects"},lock:{keywords:["security","password","padlock"],char:"\u{1f512}",fitzpatrick_scale:!1,category:"objects"},unlock:{keywords:["privacy","security"],char:"\u{1f513}",fitzpatrick_scale:!1,category:"objects"},lock_with_ink_pen:{keywords:["security","secret"],char:"\u{1f50f}",fitzpatrick_scale:!1,category:"objects"},pen:{keywords:["stationery","writing","write"],char:"\u{1f58a}",fitzpatrick_scale:!1,category:"objects"},fountain_pen:{keywords:["stationery","writing","write"],char:"\u{1f58b}",fitzpatrick_scale:!1,category:"objects"},black_nib:{keywords:["pen","stationery","writing","write"],char:"\u2712\ufe0f",fitzpatrick_scale:!1,category:"objects"},memo:{keywords:["write","documents","stationery","pencil","paper","writing","legal","exam","quiz","test","study","compose"],char:"\u{1f4dd}",fitzpatrick_scale:!1,category:"objects"},pencil2:{keywords:["stationery","write","paper","writing","school","study"],char:"\u270f\ufe0f",fitzpatrick_scale:!1,category:"objects"},crayon:{keywords:["drawing","creativity"],char:"\u{1f58d}",fitzpatrick_scale:!1,category:"objects"},paintbrush:{keywords:["drawing","creativity","art"],char:"\u{1f58c}",fitzpatrick_scale:!1,category:"objects"},mag:{keywords:["search","zoom","find","detective"],char:"\u{1f50d}",fitzpatrick_scale:!1,category:"objects"},mag_right:{keywords:["search","zoom","find","detective"],char:"\u{1f50e}",fitzpatrick_scale:!1,category:"objects"},heart:{keywords:["love","like","valentines"],char:"\u2764\ufe0f",fitzpatrick_scale:!1,category:"symbols"},orange_heart:{keywords:["love","like","affection","valentines"],char:"\u{1f9e1}",fitzpatrick_scale:!1,category:"symbols"},yellow_heart:{keywords:["love","like","affection","valentines"],char:"\u{1f49b}",fitzpatrick_scale:!1,category:"symbols"},green_heart:{keywords:["love","like","affection","valentines"],char:"\u{1f49a}",fitzpatrick_scale:!1,category:"symbols"},blue_heart:{keywords:["love","like","affection","valentines"],char:"\u{1f499}",fitzpatrick_scale:!1,category:"symbols"},purple_heart:{keywords:["love","like","affection","valentines"],char:"\u{1f49c}",fitzpatrick_scale:!1,category:"symbols"},black_heart:{keywords:["evil"],char:"\u{1f5a4}",fitzpatrick_scale:!1,category:"symbols"},broken_heart:{keywords:["sad","sorry","break","heart","heartbreak"],char:"\u{1f494}",fitzpatrick_scale:!1,category:"symbols"},heavy_heart_exclamation:{keywords:["decoration","love"],char:"\u2763",fitzpatrick_scale:!1,category:"symbols"},two_hearts:{keywords:["love","like","affection","valentines","heart"],char:"\u{1f495}",fitzpatrick_scale:!1,category:"symbols"},revolving_hearts:{keywords:["love","like","affection","valentines"],char:"\u{1f49e}",fitzpatrick_scale:!1,category:"symbols"},heartbeat:{keywords:["love","like","affection","valentines","pink","heart"],char:"\u{1f493}",fitzpatrick_scale:!1,category:"symbols"},heartpulse:{keywords:["like","love","affection","valentines","pink"],char:"\u{1f497}",fitzpatrick_scale:!1,category:"symbols"},sparkling_heart:{keywords:["love","like","affection","valentines"],char:"\u{1f496}",fitzpatrick_scale:!1,category:"symbols"},cupid:{keywords:["love","like","heart","affection","valentines"],char:"\u{1f498}",fitzpatrick_scale:!1,category:"symbols"},gift_heart:{keywords:["love","valentines"],char:"\u{1f49d}",fitzpatrick_scale:!1,category:"symbols"},heart_decoration:{keywords:["purple-square","love","like"],char:"\u{1f49f}",fitzpatrick_scale:!1,category:"symbols"},peace_symbol:{keywords:["hippie"],char:"\u262e",fitzpatrick_scale:!1,category:"symbols"},latin_cross:{keywords:["christianity"],char:"\u271d",fitzpatrick_scale:!1,category:"symbols"},star_and_crescent:{keywords:["islam"],char:"\u262a",fitzpatrick_scale:!1,category:"symbols"},om:{keywords:["hinduism","buddhism","sikhism","jainism"],char:"\u{1f549}",fitzpatrick_scale:!1,category:"symbols"},wheel_of_dharma:{keywords:["hinduism","buddhism","sikhism","jainism"],char:"\u2638",fitzpatrick_scale:!1,category:"symbols"},star_of_david:{keywords:["judaism"],char:"\u2721",fitzpatrick_scale:!1,category:"symbols"},six_pointed_star:{keywords:["purple-square","religion","jewish","hexagram"],char:"\u{1f52f}",fitzpatrick_scale:!1,category:"symbols"},menorah:{keywords:["hanukkah","candles","jewish"],char:"\u{1f54e}",fitzpatrick_scale:!1,category:"symbols"},yin_yang:{keywords:["balance"],char:"\u262f",fitzpatrick_scale:!1,category:"symbols"},orthodox_cross:{keywords:["suppedaneum","religion"],char:"\u2626",fitzpatrick_scale:!1,category:"symbols"},place_of_worship:{keywords:["religion","church","temple","prayer"],char:"\u{1f6d0}",fitzpatrick_scale:!1,category:"symbols"},ophiuchus:{keywords:["sign","purple-square","constellation","astrology"],char:"\u26ce",fitzpatrick_scale:!1,category:"symbols"},aries:{keywords:["sign","purple-square","zodiac","astrology"],char:"\u2648",fitzpatrick_scale:!1,category:"symbols"},taurus:{keywords:["purple-square","sign","zodiac","astrology"],char:"\u2649",fitzpatrick_scale:!1,category:"symbols"},gemini:{keywords:["sign","zodiac","purple-square","astrology"],char:"\u264a",fitzpatrick_scale:!1,category:"symbols"},cancer:{keywords:["sign","zodiac","purple-square","astrology"],char:"\u264b",fitzpatrick_scale:!1,category:"symbols"},leo:{keywords:["sign","purple-square","zodiac","astrology"],char:"\u264c",fitzpatrick_scale:!1,category:"symbols"},virgo:{keywords:["sign","zodiac","purple-square","astrology"],char:"\u264d",fitzpatrick_scale:!1,category:"symbols"},libra:{keywords:["sign","purple-square","zodiac","astrology"],char:"\u264e",fitzpatrick_scale:!1,category:"symbols"},scorpius:{keywords:["sign","zodiac","purple-square","astrology","scorpio"],char:"\u264f",fitzpatrick_scale:!1,category:"symbols"},sagittarius:{keywords:["sign","zodiac","purple-square","astrology"],char:"\u2650",fitzpatrick_scale:!1,category:"symbols"},capricorn:{keywords:["sign","zodiac","purple-square","astrology"],char:"\u2651",fitzpatrick_scale:!1,category:"symbols"},aquarius:{keywords:["sign","purple-square","zodiac","astrology"],char:"\u2652",fitzpatrick_scale:!1,category:"symbols"},pisces:{keywords:["purple-square","sign","zodiac","astrology"],char:"\u2653",fitzpatrick_scale:!1,category:"symbols"},id:{keywords:["purple-square","words"],char:"\u{1f194}",fitzpatrick_scale:!1,category:"symbols"},atom_symbol:{keywords:["science","physics","chemistry"],char:"\u269b",fitzpatrick_scale:!1,category:"symbols"},u7a7a:{keywords:["kanji","japanese","chinese","empty","sky","blue-square"],char:"\u{1f233}",fitzpatrick_scale:!1,category:"symbols"},u5272:{keywords:["cut","divide","chinese","kanji","pink-square"],char:"\u{1f239}",fitzpatrick_scale:!1,category:"symbols"},radioactive:{keywords:["nuclear","danger"],char:"\u2622",fitzpatrick_scale:!1,category:"symbols"},biohazard:{keywords:["danger"],char:"\u2623",fitzpatrick_scale:!1,category:"symbols"},mobile_phone_off:{keywords:["mute","orange-square","silence","quiet"],char:"\u{1f4f4}",fitzpatrick_scale:!1,category:"symbols"},vibration_mode:{keywords:["orange-square","phone"],char:"\u{1f4f3}",fitzpatrick_scale:!1,category:"symbols"},u6709:{keywords:["orange-square","chinese","have","kanji"],char:"\u{1f236}",fitzpatrick_scale:!1,category:"symbols"},u7121:{keywords:["nothing","chinese","kanji","japanese","orange-square"],char:"\u{1f21a}",fitzpatrick_scale:!1,category:"symbols"},u7533:{keywords:["chinese","japanese","kanji","orange-square"],char:"\u{1f238}",fitzpatrick_scale:!1,category:"symbols"},u55b6:{keywords:["japanese","opening hours","orange-square"],char:"\u{1f23a}",fitzpatrick_scale:!1,category:"symbols"},u6708:{keywords:["chinese","month","moon","japanese","orange-square","kanji"],char:"\u{1f237}\ufe0f",fitzpatrick_scale:!1,category:"symbols"},eight_pointed_black_star:{keywords:["orange-square","shape","polygon"],char:"\u2734\ufe0f",fitzpatrick_scale:!1,category:"symbols"},vs:{keywords:["words","orange-square"],char:"\u{1f19a}",fitzpatrick_scale:!1,category:"symbols"},accept:{keywords:["ok","good","chinese","kanji","agree","yes","orange-circle"],char:"\u{1f251}",fitzpatrick_scale:!1,category:"symbols"},white_flower:{keywords:["japanese","spring"],char:"\u{1f4ae}",fitzpatrick_scale:!1,category:"symbols"},ideograph_advantage:{keywords:["chinese","kanji","obtain","get","circle"],char:"\u{1f250}",fitzpatrick_scale:!1,category:"symbols"},secret:{keywords:["privacy","chinese","sshh","kanji","red-circle"],char:"\u3299\ufe0f",fitzpatrick_scale:!1,category:"symbols"},congratulations:{keywords:["chinese","kanji","japanese","red-circle"],char:"\u3297\ufe0f",fitzpatrick_scale:!1,category:"symbols"},u5408:{keywords:["japanese","chinese","join","kanji","red-square"],char:"\u{1f234}",fitzpatrick_scale:!1,category:"symbols"},u6e80:{keywords:["full","chinese","japanese","red-square","kanji"],char:"\u{1f235}",fitzpatrick_scale:!1,category:"symbols"},u7981:{keywords:["kanji","japanese","chinese","forbidden","limit","restricted","red-square"],char:"\u{1f232}",fitzpatrick_scale:!1,category:"symbols"},a:{keywords:["red-square","alphabet","letter"],char:"\u{1f170}\ufe0f",fitzpatrick_scale:!1,category:"symbols"},b:{keywords:["red-square","alphabet","letter"],char:"\u{1f171}\ufe0f",fitzpatrick_scale:!1,category:"symbols"},ab:{keywords:["red-square","alphabet"],char:"\u{1f18e}",fitzpatrick_scale:!1,category:"symbols"},cl:{keywords:["alphabet","words","red-square"],char:"\u{1f191}",fitzpatrick_scale:!1,category:"symbols"},o2:{keywords:["alphabet","red-square","letter"],char:"\u{1f17e}\ufe0f",fitzpatrick_scale:!1,category:"symbols"},sos:{keywords:["help","red-square","words","emergency","911"],char:"\u{1f198}",fitzpatrick_scale:!1,category:"symbols"},no_entry:{keywords:["limit","security","privacy","bad","denied","stop","circle"],char:"\u26d4",fitzpatrick_scale:!1,category:"symbols"},name_badge:{keywords:["fire","forbid"],char:"\u{1f4db}",fitzpatrick_scale:!1,category:"symbols"},no_entry_sign:{keywords:["forbid","stop","limit","denied","disallow","circle"],char:"\u{1f6ab}",fitzpatrick_scale:!1,category:"symbols"},x:{keywords:["no","delete","remove","cancel","red"],char:"\u274c",fitzpatrick_scale:!1,category:"symbols"},o:{keywords:["circle","round"],char:"\u2b55",fitzpatrick_scale:!1,category:"symbols"},stop_sign:{keywords:["stop"],char:"\u{1f6d1}",fitzpatrick_scale:!1,category:"symbols"},anger:{keywords:["angry","mad"],char:"\u{1f4a2}",fitzpatrick_scale:!1,category:"symbols"},hotsprings:{keywords:["bath","warm","relax"],char:"\u2668\ufe0f",fitzpatrick_scale:!1,category:"symbols"},no_pedestrians:{keywords:["rules","crossing","walking","circle"],char:"\u{1f6b7}",fitzpatrick_scale:!1,category:"symbols"},do_not_litter:{keywords:["trash","bin","garbage","circle"],char:"\u{1f6af}",fitzpatrick_scale:!1,category:"symbols"},no_bicycles:{keywords:["cyclist","prohibited","circle"],char:"\u{1f6b3}",fitzpatrick_scale:!1,category:"symbols"},"non-potable_water":{keywords:["drink","faucet","tap","circle"],char:"\u{1f6b1}",fitzpatrick_scale:!1,category:"symbols"},underage:{keywords:["18","drink","pub","night","minor","circle"],char:"\u{1f51e}",fitzpatrick_scale:!1,category:"symbols"},no_mobile_phones:{keywords:["iphone","mute","circle"],char:"\u{1f4f5}",fitzpatrick_scale:!1,category:"symbols"},exclamation:{keywords:["heavy_exclamation_mark","danger","surprise","punctuation","wow","warning"],char:"\u2757",fitzpatrick_scale:!1,category:"symbols"},grey_exclamation:{keywords:["surprise","punctuation","gray","wow","warning"],char:"\u2755",fitzpatrick_scale:!1,category:"symbols"},question:{keywords:["doubt","confused"],char:"\u2753",fitzpatrick_scale:!1,category:"symbols"},grey_question:{keywords:["doubts","gray","huh","confused"],char:"\u2754",fitzpatrick_scale:!1,category:"symbols"},bangbang:{keywords:["exclamation","surprise"],char:"\u203c\ufe0f",fitzpatrick_scale:!1,category:"symbols"},interrobang:{keywords:["wat","punctuation","surprise"],char:"\u2049\ufe0f",fitzpatrick_scale:!1,category:"symbols"},100:{keywords:["score","perfect","numbers","century","exam","quiz","test","pass","hundred"],char:"\u{1f4af}",fitzpatrick_scale:!1,category:"symbols"},low_brightness:{keywords:["sun","afternoon","warm","summer"],char:"\u{1f505}",fitzpatrick_scale:!1,category:"symbols"},high_brightness:{keywords:["sun","light"],char:"\u{1f506}",fitzpatrick_scale:!1,category:"symbols"},trident:{keywords:["weapon","spear"],char:"\u{1f531}",fitzpatrick_scale:!1,category:"symbols"},fleur_de_lis:{keywords:["decorative","scout"],char:"\u269c",fitzpatrick_scale:!1,category:"symbols"},part_alternation_mark:{keywords:["graph","presentation","stats","business","economics","bad"],char:"\u303d\ufe0f",fitzpatrick_scale:!1,category:"symbols"},warning:{keywords:["exclamation","wip","alert","error","problem","issue"],char:"\u26a0\ufe0f",fitzpatrick_scale:!1,category:"symbols"},children_crossing:{keywords:["school","warning","danger","sign","driving","yellow-diamond"],char:"\u{1f6b8}",fitzpatrick_scale:!1,category:"symbols"},beginner:{keywords:["badge","shield"],char:"\u{1f530}",fitzpatrick_scale:!1,category:"symbols"},recycle:{keywords:["arrow","environment","garbage","trash"],char:"\u267b\ufe0f",fitzpatrick_scale:!1,category:"symbols"},u6307:{keywords:["chinese","point","green-square","kanji"],char:"\u{1f22f}",fitzpatrick_scale:!1,category:"symbols"},chart:{keywords:["green-square","graph","presentation","stats"],char:"\u{1f4b9}",fitzpatrick_scale:!1,category:"symbols"},sparkle:{keywords:["stars","green-square","awesome","good","fireworks"],char:"\u2747\ufe0f",fitzpatrick_scale:!1,category:"symbols"},eight_spoked_asterisk:{keywords:["star","sparkle","green-square"],char:"\u2733\ufe0f",fitzpatrick_scale:!1,category:"symbols"},negative_squared_cross_mark:{keywords:["x","green-square","no","deny"],char:"\u274e",fitzpatrick_scale:!1,category:"symbols"},white_check_mark:{keywords:["green-square","ok","agree","vote","election","answer","tick"],char:"\u2705",fitzpatrick_scale:!1,category:"symbols"},diamond_shape_with_a_dot_inside:{keywords:["jewel","blue","gem","crystal","fancy"],char:"\u{1f4a0}",fitzpatrick_scale:!1,category:"symbols"},cyclone:{keywords:["weather","swirl","blue","cloud","vortex","spiral","whirlpool","spin","tornado","hurricane","typhoon"],char:"\u{1f300}",fitzpatrick_scale:!1,category:"symbols"},loop:{keywords:["tape","cassette"],char:"\u27bf",fitzpatrick_scale:!1,category:"symbols"},globe_with_meridians:{keywords:["earth","international","world","internet","interweb","i18n"],char:"\u{1f310}",fitzpatrick_scale:!1,category:"symbols"},m:{keywords:["alphabet","blue-circle","letter"],char:"\u24c2\ufe0f",fitzpatrick_scale:!1,category:"symbols"},atm:{keywords:["money","sales","cash","blue-square","payment","bank"],char:"\u{1f3e7}",fitzpatrick_scale:!1,category:"symbols"},sa:{keywords:["japanese","blue-square","katakana"],char:"\u{1f202}\ufe0f",fitzpatrick_scale:!1,category:"symbols"},passport_control:{keywords:["custom","blue-square"],char:"\u{1f6c2}",fitzpatrick_scale:!1,category:"symbols"},customs:{keywords:["passport","border","blue-square"],char:"\u{1f6c3}",fitzpatrick_scale:!1,category:"symbols"},baggage_claim:{keywords:["blue-square","airport","transport"],char:"\u{1f6c4}",fitzpatrick_scale:!1,category:"symbols"},left_luggage:{keywords:["blue-square","travel"],char:"\u{1f6c5}",fitzpatrick_scale:!1,category:"symbols"},wheelchair:{keywords:["blue-square","disabled","a11y","accessibility"],char:"\u267f",fitzpatrick_scale:!1,category:"symbols"},no_smoking:{keywords:["cigarette","blue-square","smell","smoke"],char:"\u{1f6ad}",fitzpatrick_scale:!1,category:"symbols"},wc:{keywords:["toilet","restroom","blue-square"],char:"\u{1f6be}",fitzpatrick_scale:!1,category:"symbols"},parking:{keywords:["cars","blue-square","alphabet","letter"],char:"\u{1f17f}\ufe0f",fitzpatrick_scale:!1,category:"symbols"},potable_water:{keywords:["blue-square","liquid","restroom","cleaning","faucet"],char:"\u{1f6b0}",fitzpatrick_scale:!1,category:"symbols"},mens:{keywords:["toilet","restroom","wc","blue-square","gender","male"],char:"\u{1f6b9}",fitzpatrick_scale:!1,category:"symbols"},womens:{keywords:["purple-square","woman","female","toilet","loo","restroom","gender"],char:"\u{1f6ba}",fitzpatrick_scale:!1,category:"symbols"},baby_symbol:{keywords:["orange-square","child"],char:"\u{1f6bc}",fitzpatrick_scale:!1,category:"symbols"},restroom:{keywords:["blue-square","toilet","refresh","wc","gender"],char:"\u{1f6bb}",fitzpatrick_scale:!1,category:"symbols"},put_litter_in_its_place:{keywords:["blue-square","sign","human","info"],char:"\u{1f6ae}",fitzpatrick_scale:!1,category:"symbols"},cinema:{keywords:["blue-square","record","film","movie","curtain","stage","theater"],char:"\u{1f3a6}",fitzpatrick_scale:!1,category:"symbols"},signal_strength:{keywords:["blue-square","reception","phone","internet","connection","wifi","bluetooth","bars"],char:"\u{1f4f6}",fitzpatrick_scale:!1,category:"symbols"},koko:{keywords:["blue-square","here","katakana","japanese","destination"],char:"\u{1f201}",fitzpatrick_scale:!1,category:"symbols"},ng:{keywords:["blue-square","words","shape","icon"],char:"\u{1f196}",fitzpatrick_scale:!1,category:"symbols"},ok:{keywords:["good","agree","yes","blue-square"],char:"\u{1f197}",fitzpatrick_scale:!1,category:"symbols"},up:{keywords:["blue-square","above","high"],char:"\u{1f199}",fitzpatrick_scale:!1,category:"symbols"},cool:{keywords:["words","blue-square"],char:"\u{1f192}",fitzpatrick_scale:!1,category:"symbols"},new:{keywords:["blue-square","words","start"],char:"\u{1f195}",fitzpatrick_scale:!1,category:"symbols"},free:{keywords:["blue-square","words"],char:"\u{1f193}",fitzpatrick_scale:!1,category:"symbols"},zero:{keywords:["0","numbers","blue-square","null"],char:"0\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},one:{keywords:["blue-square","numbers","1"],char:"1\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},two:{keywords:["numbers","2","prime","blue-square"],char:"2\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},three:{keywords:["3","numbers","prime","blue-square"],char:"3\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},four:{keywords:["4","numbers","blue-square"],char:"4\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},five:{keywords:["5","numbers","blue-square","prime"],char:"5\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},six:{keywords:["6","numbers","blue-square"],char:"6\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},seven:{keywords:["7","numbers","blue-square","prime"],char:"7\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},eight:{keywords:["8","blue-square","numbers"],char:"8\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},nine:{keywords:["blue-square","numbers","9"],char:"9\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},keycap_ten:{keywords:["numbers","10","blue-square"],char:"\u{1f51f}",fitzpatrick_scale:!1,category:"symbols"},asterisk:{keywords:["star","keycap"],char:"*\u20e3",fitzpatrick_scale:!1,category:"symbols"},1234:{keywords:["numbers","blue-square"],char:"\u{1f522}",fitzpatrick_scale:!1,category:"symbols"},eject_button:{keywords:["blue-square"],char:"\u23cf\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_forward:{keywords:["blue-square","right","direction","play"],char:"\u25b6\ufe0f",fitzpatrick_scale:!1,category:"symbols"},pause_button:{keywords:["pause","blue-square"],char:"\u23f8",fitzpatrick_scale:!1,category:"symbols"},next_track_button:{keywords:["forward","next","blue-square"],char:"\u23ed",fitzpatrick_scale:!1,category:"symbols"},stop_button:{keywords:["blue-square"],char:"\u23f9",fitzpatrick_scale:!1,category:"symbols"},record_button:{keywords:["blue-square"],char:"\u23fa",fitzpatrick_scale:!1,category:"symbols"},play_or_pause_button:{keywords:["blue-square","play","pause"],char:"\u23ef",fitzpatrick_scale:!1,category:"symbols"},previous_track_button:{keywords:["backward"],char:"\u23ee",fitzpatrick_scale:!1,category:"symbols"},fast_forward:{keywords:["blue-square","play","speed","continue"],char:"\u23e9",fitzpatrick_scale:!1,category:"symbols"},rewind:{keywords:["play","blue-square"],char:"\u23ea",fitzpatrick_scale:!1,category:"symbols"},twisted_rightwards_arrows:{keywords:["blue-square","shuffle","music","random"],char:"\u{1f500}",fitzpatrick_scale:!1,category:"symbols"},repeat:{keywords:["loop","record"],char:"\u{1f501}",fitzpatrick_scale:!1,category:"symbols"},repeat_one:{keywords:["blue-square","loop"],char:"\u{1f502}",fitzpatrick_scale:!1,category:"symbols"},arrow_backward:{keywords:["blue-square","left","direction"],char:"\u25c0\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_up_small:{keywords:["blue-square","triangle","direction","point","forward","top"],char:"\u{1f53c}",fitzpatrick_scale:!1,category:"symbols"},arrow_down_small:{keywords:["blue-square","direction","bottom"],char:"\u{1f53d}",fitzpatrick_scale:!1,category:"symbols"},arrow_double_up:{keywords:["blue-square","direction","top"],char:"\u23eb",fitzpatrick_scale:!1,category:"symbols"},arrow_double_down:{keywords:["blue-square","direction","bottom"],char:"\u23ec",fitzpatrick_scale:!1,category:"symbols"},arrow_right:{keywords:["blue-square","next"],char:"\u27a1\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_left:{keywords:["blue-square","previous","back"],char:"\u2b05\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_up:{keywords:["blue-square","continue","top","direction"],char:"\u2b06\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_down:{keywords:["blue-square","direction","bottom"],char:"\u2b07\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_upper_right:{keywords:["blue-square","point","direction","diagonal","northeast"],char:"\u2197\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_lower_right:{keywords:["blue-square","direction","diagonal","southeast"],char:"\u2198\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_lower_left:{keywords:["blue-square","direction","diagonal","southwest"],char:"\u2199\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_upper_left:{keywords:["blue-square","point","direction","diagonal","northwest"],char:"\u2196\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_up_down:{keywords:["blue-square","direction","way","vertical"],char:"\u2195\ufe0f",fitzpatrick_scale:!1,category:"symbols"},left_right_arrow:{keywords:["shape","direction","horizontal","sideways"],char:"\u2194\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrows_counterclockwise:{keywords:["blue-square","sync","cycle"],char:"\u{1f504}",fitzpatrick_scale:!1,category:"symbols"},arrow_right_hook:{keywords:["blue-square","return","rotate","direction"],char:"\u21aa\ufe0f",fitzpatrick_scale:!1,category:"symbols"},leftwards_arrow_with_hook:{keywords:["back","return","blue-square","undo","enter"],char:"\u21a9\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_heading_up:{keywords:["blue-square","direction","top"],char:"\u2934\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrow_heading_down:{keywords:["blue-square","direction","bottom"],char:"\u2935\ufe0f",fitzpatrick_scale:!1,category:"symbols"},hash:{keywords:["symbol","blue-square","twitter"],char:"#\ufe0f\u20e3",fitzpatrick_scale:!1,category:"symbols"},information_source:{keywords:["blue-square","alphabet","letter"],char:"\u2139\ufe0f",fitzpatrick_scale:!1,category:"symbols"},abc:{keywords:["blue-square","alphabet"],char:"\u{1f524}",fitzpatrick_scale:!1,category:"symbols"},abcd:{keywords:["blue-square","alphabet"],char:"\u{1f521}",fitzpatrick_scale:!1,category:"symbols"},capital_abcd:{keywords:["alphabet","words","blue-square"],char:"\u{1f520}",fitzpatrick_scale:!1,category:"symbols"},symbols:{keywords:["blue-square","music","note","ampersand","percent","glyphs","characters"],char:"\u{1f523}",fitzpatrick_scale:!1,category:"symbols"},musical_note:{keywords:["score","tone","sound"],char:"\u{1f3b5}",fitzpatrick_scale:!1,category:"symbols"},notes:{keywords:["music","score"],char:"\u{1f3b6}",fitzpatrick_scale:!1,category:"symbols"},wavy_dash:{keywords:["draw","line","moustache","mustache","squiggle","scribble"],char:"\u3030\ufe0f",fitzpatrick_scale:!1,category:"symbols"},curly_loop:{keywords:["scribble","draw","shape","squiggle"],char:"\u27b0",fitzpatrick_scale:!1,category:"symbols"},heavy_check_mark:{keywords:["ok","nike","answer","yes","tick"],char:"\u2714\ufe0f",fitzpatrick_scale:!1,category:"symbols"},arrows_clockwise:{keywords:["sync","cycle","round","repeat"],char:"\u{1f503}",fitzpatrick_scale:!1,category:"symbols"},heavy_plus_sign:{keywords:["math","calculation","addition","more","increase"],char:"\u2795",fitzpatrick_scale:!1,category:"symbols"},heavy_minus_sign:{keywords:["math","calculation","subtract","less"],char:"\u2796",fitzpatrick_scale:!1,category:"symbols"},heavy_division_sign:{keywords:["divide","math","calculation"],char:"\u2797",fitzpatrick_scale:!1,category:"symbols"},heavy_multiplication_x:{keywords:["math","calculation"],char:"\u2716\ufe0f",fitzpatrick_scale:!1,category:"symbols"},infinity:{keywords:["forever"],char:"\u267e",fitzpatrick_scale:!1,category:"symbols"},heavy_dollar_sign:{keywords:["money","sales","payment","currency","buck"],char:"\u{1f4b2}",fitzpatrick_scale:!1,category:"symbols"},currency_exchange:{keywords:["money","sales","dollar","travel"],char:"\u{1f4b1}",fitzpatrick_scale:!1,category:"symbols"},copyright:{keywords:["ip","license","circle","law","legal"],char:"\xa9\ufe0f",fitzpatrick_scale:!1,category:"symbols"},registered:{keywords:["alphabet","circle"],char:"\xae\ufe0f",fitzpatrick_scale:!1,category:"symbols"},tm:{keywords:["trademark","brand","law","legal"],char:"\u2122\ufe0f",fitzpatrick_scale:!1,category:"symbols"},end:{keywords:["words","arrow"],char:"\u{1f51a}",fitzpatrick_scale:!1,category:"symbols"},back:{keywords:["arrow","words","return"],char:"\u{1f519}",fitzpatrick_scale:!1,category:"symbols"},on:{keywords:["arrow","words"],char:"\u{1f51b}",fitzpatrick_scale:!1,category:"symbols"},top:{keywords:["words","blue-square"],char:"\u{1f51d}",fitzpatrick_scale:!1,category:"symbols"},soon:{keywords:["arrow","words"],char:"\u{1f51c}",fitzpatrick_scale:!1,category:"symbols"},ballot_box_with_check:{keywords:["ok","agree","confirm","black-square","vote","election","yes","tick"],char:"\u2611\ufe0f",fitzpatrick_scale:!1,category:"symbols"},radio_button:{keywords:["input","old","music","circle"],char:"\u{1f518}",fitzpatrick_scale:!1,category:"symbols"},white_circle:{keywords:["shape","round"],char:"\u26aa",fitzpatrick_scale:!1,category:"symbols"},black_circle:{keywords:["shape","button","round"],char:"\u26ab",fitzpatrick_scale:!1,category:"symbols"},red_circle:{keywords:["shape","error","danger"],char:"\u{1f534}",fitzpatrick_scale:!1,category:"symbols"},large_blue_circle:{keywords:["shape","icon","button"],char:"\u{1f535}",fitzpatrick_scale:!1,category:"symbols"},small_orange_diamond:{keywords:["shape","jewel","gem"],char:"\u{1f538}",fitzpatrick_scale:!1,category:"symbols"},small_blue_diamond:{keywords:["shape","jewel","gem"],char:"\u{1f539}",fitzpatrick_scale:!1,category:"symbols"},large_orange_diamond:{keywords:["shape","jewel","gem"],char:"\u{1f536}",fitzpatrick_scale:!1,category:"symbols"},large_blue_diamond:{keywords:["shape","jewel","gem"],char:"\u{1f537}",fitzpatrick_scale:!1,category:"symbols"},small_red_triangle:{keywords:["shape","direction","up","top"],char:"\u{1f53a}",fitzpatrick_scale:!1,category:"symbols"},black_small_square:{keywords:["shape","icon"],char:"\u25aa\ufe0f",fitzpatrick_scale:!1,category:"symbols"},white_small_square:{keywords:["shape","icon"],char:"\u25ab\ufe0f",fitzpatrick_scale:!1,category:"symbols"},black_large_square:{keywords:["shape","icon","button"],char:"\u2b1b",fitzpatrick_scale:!1,category:"symbols"},white_large_square:{keywords:["shape","icon","stone","button"],char:"\u2b1c",fitzpatrick_scale:!1,category:"symbols"},small_red_triangle_down:{keywords:["shape","direction","bottom"],char:"\u{1f53b}",fitzpatrick_scale:!1,category:"symbols"},black_medium_square:{keywords:["shape","button","icon"],char:"\u25fc\ufe0f",fitzpatrick_scale:!1,category:"symbols"},white_medium_square:{keywords:["shape","stone","icon"],char:"\u25fb\ufe0f",fitzpatrick_scale:!1,category:"symbols"},black_medium_small_square:{keywords:["icon","shape","button"],char:"\u25fe",fitzpatrick_scale:!1,category:"symbols"},white_medium_small_square:{keywords:["shape","stone","icon","button"],char:"\u25fd",fitzpatrick_scale:!1,category:"symbols"},black_square_button:{keywords:["shape","input","frame"],char:"\u{1f532}",fitzpatrick_scale:!1,category:"symbols"},white_square_button:{keywords:["shape","input"],char:"\u{1f533}",fitzpatrick_scale:!1,category:"symbols"},speaker:{keywords:["sound","volume","silence","broadcast"],char:"\u{1f508}",fitzpatrick_scale:!1,category:"symbols"},sound:{keywords:["volume","speaker","broadcast"],char:"\u{1f509}",fitzpatrick_scale:!1,category:"symbols"},loud_sound:{keywords:["volume","noise","noisy","speaker","broadcast"],char:"\u{1f50a}",fitzpatrick_scale:!1,category:"symbols"},mute:{keywords:["sound","volume","silence","quiet"],char:"\u{1f507}",fitzpatrick_scale:!1,category:"symbols"},mega:{keywords:["sound","speaker","volume"],char:"\u{1f4e3}",fitzpatrick_scale:!1,category:"symbols"},loudspeaker:{keywords:["volume","sound"],char:"\u{1f4e2}",fitzpatrick_scale:!1,category:"symbols"},bell:{keywords:["sound","notification","christmas","xmas","chime"],char:"\u{1f514}",fitzpatrick_scale:!1,category:"symbols"},no_bell:{keywords:["sound","volume","mute","quiet","silent"],char:"\u{1f515}",fitzpatrick_scale:!1,category:"symbols"},black_joker:{keywords:["poker","cards","game","play","magic"],char:"\u{1f0cf}",fitzpatrick_scale:!1,category:"symbols"},mahjong:{keywords:["game","play","chinese","kanji"],char:"\u{1f004}",fitzpatrick_scale:!1,category:"symbols"},spades:{keywords:["poker","cards","suits","magic"],char:"\u2660\ufe0f",fitzpatrick_scale:!1,category:"symbols"},clubs:{keywords:["poker","cards","magic","suits"],char:"\u2663\ufe0f",fitzpatrick_scale:!1,category:"symbols"},hearts:{keywords:["poker","cards","magic","suits"],char:"\u2665\ufe0f",fitzpatrick_scale:!1,category:"symbols"},diamonds:{keywords:["poker","cards","magic","suits"],char:"\u2666\ufe0f",fitzpatrick_scale:!1,category:"symbols"},flower_playing_cards:{keywords:["game","sunset","red"],char:"\u{1f3b4}",fitzpatrick_scale:!1,category:"symbols"},thought_balloon:{keywords:["bubble","cloud","speech","thinking","dream"],char:"\u{1f4ad}",fitzpatrick_scale:!1,category:"symbols"},right_anger_bubble:{keywords:["caption","speech","thinking","mad"],char:"\u{1f5ef}",fitzpatrick_scale:!1,category:"symbols"},speech_balloon:{keywords:["bubble","words","message","talk","chatting"],char:"\u{1f4ac}",fitzpatrick_scale:!1,category:"symbols"},left_speech_bubble:{keywords:["words","message","talk","chatting"],char:"\u{1f5e8}",fitzpatrick_scale:!1,category:"symbols"},clock1:{keywords:["time","late","early","schedule"],char:"\u{1f550}",fitzpatrick_scale:!1,category:"symbols"},clock2:{keywords:["time","late","early","schedule"],char:"\u{1f551}",fitzpatrick_scale:!1,category:"symbols"},clock3:{keywords:["time","late","early","schedule"],char:"\u{1f552}",fitzpatrick_scale:!1,category:"symbols"},clock4:{keywords:["time","late","early","schedule"],char:"\u{1f553}",fitzpatrick_scale:!1,category:"symbols"},clock5:{keywords:["time","late","early","schedule"],char:"\u{1f554}",fitzpatrick_scale:!1,category:"symbols"},clock6:{keywords:["time","late","early","schedule","dawn","dusk"],char:"\u{1f555}",fitzpatrick_scale:!1,category:"symbols"},clock7:{keywords:["time","late","early","schedule"],char:"\u{1f556}",fitzpatrick_scale:!1,category:"symbols"},clock8:{keywords:["time","late","early","schedule"],char:"\u{1f557}",fitzpatrick_scale:!1,category:"symbols"},clock9:{keywords:["time","late","early","schedule"],char:"\u{1f558}",fitzpatrick_scale:!1,category:"symbols"},clock10:{keywords:["time","late","early","schedule"],char:"\u{1f559}",fitzpatrick_scale:!1,category:"symbols"},clock11:{keywords:["time","late","early","schedule"],char:"\u{1f55a}",fitzpatrick_scale:!1,category:"symbols"},clock12:{keywords:["time","noon","midnight","midday","late","early","schedule"],char:"\u{1f55b}",fitzpatrick_scale:!1,category:"symbols"},clock130:{keywords:["time","late","early","schedule"],char:"\u{1f55c}",fitzpatrick_scale:!1,category:"symbols"},clock230:{keywords:["time","late","early","schedule"],char:"\u{1f55d}",fitzpatrick_scale:!1,category:"symbols"},clock330:{keywords:["time","late","early","schedule"],char:"\u{1f55e}",fitzpatrick_scale:!1,category:"symbols"},clock430:{keywords:["time","late","early","schedule"],char:"\u{1f55f}",fitzpatrick_scale:!1,category:"symbols"},clock530:{keywords:["time","late","early","schedule"],char:"\u{1f560}",fitzpatrick_scale:!1,category:"symbols"},clock630:{keywords:["time","late","early","schedule"],char:"\u{1f561}",fitzpatrick_scale:!1,category:"symbols"},clock730:{keywords:["time","late","early","schedule"],char:"\u{1f562}",fitzpatrick_scale:!1,category:"symbols"},clock830:{keywords:["time","late","early","schedule"],char:"\u{1f563}",fitzpatrick_scale:!1,category:"symbols"},clock930:{keywords:["time","late","early","schedule"],char:"\u{1f564}",fitzpatrick_scale:!1,category:"symbols"},clock1030:{keywords:["time","late","early","schedule"],char:"\u{1f565}",fitzpatrick_scale:!1,category:"symbols"},clock1130:{keywords:["time","late","early","schedule"],char:"\u{1f566}",fitzpatrick_scale:!1,category:"symbols"},clock1230:{keywords:["time","late","early","schedule"],char:"\u{1f567}",fitzpatrick_scale:!1,category:"symbols"},afghanistan:{keywords:["af","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},aland_islands:{keywords:["\xc5land","islands","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1fd}",fitzpatrick_scale:!1,category:"flags"},albania:{keywords:["al","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},algeria:{keywords:["dz","flag","nation","country","banner"],char:"\u{1f1e9}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},american_samoa:{keywords:["american","ws","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},andorra:{keywords:["ad","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},angola:{keywords:["ao","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},anguilla:{keywords:["ai","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},antarctica:{keywords:["aq","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1f6}",fitzpatrick_scale:!1,category:"flags"},antigua_barbuda:{keywords:["antigua","barbuda","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},argentina:{keywords:["ar","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},armenia:{keywords:["am","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},aruba:{keywords:["aw","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},australia:{keywords:["au","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},austria:{keywords:["at","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},azerbaijan:{keywords:["az","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},bahamas:{keywords:["bs","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},bahrain:{keywords:["bh","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},bangladesh:{keywords:["bd","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},barbados:{keywords:["bb","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1e7}",fitzpatrick_scale:!1,category:"flags"},belarus:{keywords:["by","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},belgium:{keywords:["be","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},belize:{keywords:["bz","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},benin:{keywords:["bj","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1ef}",fitzpatrick_scale:!1,category:"flags"},bermuda:{keywords:["bm","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},bhutan:{keywords:["bt","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},bolivia:{keywords:["bo","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},caribbean_netherlands:{keywords:["bonaire","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f6}",fitzpatrick_scale:!1,category:"flags"},bosnia_herzegovina:{keywords:["bosnia","herzegovina","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},botswana:{keywords:["bw","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},brazil:{keywords:["br","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},british_indian_ocean_territory:{keywords:["british","indian","ocean","territory","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},british_virgin_islands:{keywords:["british","virgin","islands","bvi","flag","nation","country","banner"],char:"\u{1f1fb}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},brunei:{keywords:["bn","darussalam","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},bulgaria:{keywords:["bg","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},burkina_faso:{keywords:["burkina","faso","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},burundi:{keywords:["bi","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},cape_verde:{keywords:["cabo","verde","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1fb}",fitzpatrick_scale:!1,category:"flags"},cambodia:{keywords:["kh","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},cameroon:{keywords:["cm","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},canada:{keywords:["ca","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},canary_islands:{keywords:["canary","islands","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},cayman_islands:{keywords:["cayman","islands","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},central_african_republic:{keywords:["central","african","republic","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},chad:{keywords:["td","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},chile:{keywords:["flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},cn:{keywords:["china","chinese","prc","flag","country","nation","banner"],char:"\u{1f1e8}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},christmas_island:{keywords:["christmas","island","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1fd}",fitzpatrick_scale:!1,category:"flags"},cocos_islands:{keywords:["cocos","keeling","islands","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},colombia:{keywords:["co","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},comoros:{keywords:["km","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},congo_brazzaville:{keywords:["congo","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},congo_kinshasa:{keywords:["congo","democratic","republic","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},cook_islands:{keywords:["cook","islands","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},costa_rica:{keywords:["costa","rica","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},croatia:{keywords:["hr","flag","nation","country","banner"],char:"\u{1f1ed}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},cuba:{keywords:["cu","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},curacao:{keywords:["cura\xe7ao","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},cyprus:{keywords:["cy","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},czech_republic:{keywords:["cz","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},denmark:{keywords:["dk","flag","nation","country","banner"],char:"\u{1f1e9}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},djibouti:{keywords:["dj","flag","nation","country","banner"],char:"\u{1f1e9}\u{1f1ef}",fitzpatrick_scale:!1,category:"flags"},dominica:{keywords:["dm","flag","nation","country","banner"],char:"\u{1f1e9}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},dominican_republic:{keywords:["dominican","republic","flag","nation","country","banner"],char:"\u{1f1e9}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},ecuador:{keywords:["ec","flag","nation","country","banner"],char:"\u{1f1ea}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},egypt:{keywords:["eg","flag","nation","country","banner"],char:"\u{1f1ea}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},el_salvador:{keywords:["el","salvador","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1fb}",fitzpatrick_scale:!1,category:"flags"},equatorial_guinea:{keywords:["equatorial","gn","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f6}",fitzpatrick_scale:!1,category:"flags"},eritrea:{keywords:["er","flag","nation","country","banner"],char:"\u{1f1ea}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},estonia:{keywords:["ee","flag","nation","country","banner"],char:"\u{1f1ea}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},ethiopia:{keywords:["et","flag","nation","country","banner"],char:"\u{1f1ea}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},eu:{keywords:["european","union","flag","banner"],char:"\u{1f1ea}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},falkland_islands:{keywords:["falkland","islands","malvinas","flag","nation","country","banner"],char:"\u{1f1eb}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},faroe_islands:{keywords:["faroe","islands","flag","nation","country","banner"],char:"\u{1f1eb}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},fiji:{keywords:["fj","flag","nation","country","banner"],char:"\u{1f1eb}\u{1f1ef}",fitzpatrick_scale:!1,category:"flags"},finland:{keywords:["fi","flag","nation","country","banner"],char:"\u{1f1eb}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},fr:{keywords:["banner","flag","nation","france","french","country"],char:"\u{1f1eb}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},french_guiana:{keywords:["french","guiana","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},french_polynesia:{keywords:["french","polynesia","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},french_southern_territories:{keywords:["french","southern","territories","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},gabon:{keywords:["ga","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},gambia:{keywords:["gm","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},georgia:{keywords:["ge","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},de:{keywords:["german","nation","flag","country","banner"],char:"\u{1f1e9}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},ghana:{keywords:["gh","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},gibraltar:{keywords:["gi","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},greece:{keywords:["gr","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},greenland:{keywords:["gl","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},grenada:{keywords:["gd","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},guadeloupe:{keywords:["gp","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f5}",fitzpatrick_scale:!1,category:"flags"},guam:{keywords:["gu","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},guatemala:{keywords:["gt","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},guernsey:{keywords:["gg","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},guinea:{keywords:["gn","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},guinea_bissau:{keywords:["gw","bissau","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},guyana:{keywords:["gy","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},haiti:{keywords:["ht","flag","nation","country","banner"],char:"\u{1f1ed}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},honduras:{keywords:["hn","flag","nation","country","banner"],char:"\u{1f1ed}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},hong_kong:{keywords:["hong","kong","flag","nation","country","banner"],char:"\u{1f1ed}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},hungary:{keywords:["hu","flag","nation","country","banner"],char:"\u{1f1ed}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},iceland:{keywords:["is","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},india:{keywords:["in","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},indonesia:{keywords:["flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},iran:{keywords:["iran,","islamic","republic","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},iraq:{keywords:["iq","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f6}",fitzpatrick_scale:!1,category:"flags"},ireland:{keywords:["ie","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},isle_of_man:{keywords:["isle","man","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},israel:{keywords:["il","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},it:{keywords:["italy","flag","nation","country","banner"],char:"\u{1f1ee}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},cote_divoire:{keywords:["ivory","coast","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},jamaica:{keywords:["jm","flag","nation","country","banner"],char:"\u{1f1ef}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},jp:{keywords:["japanese","nation","flag","country","banner"],char:"\u{1f1ef}\u{1f1f5}",fitzpatrick_scale:!1,category:"flags"},jersey:{keywords:["je","flag","nation","country","banner"],char:"\u{1f1ef}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},jordan:{keywords:["jo","flag","nation","country","banner"],char:"\u{1f1ef}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},kazakhstan:{keywords:["kz","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},kenya:{keywords:["ke","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},kiribati:{keywords:["ki","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},kosovo:{keywords:["xk","flag","nation","country","banner"],char:"\u{1f1fd}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},kuwait:{keywords:["kw","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},kyrgyzstan:{keywords:["kg","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},laos:{keywords:["lao","democratic","republic","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},latvia:{keywords:["lv","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1fb}",fitzpatrick_scale:!1,category:"flags"},lebanon:{keywords:["lb","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1e7}",fitzpatrick_scale:!1,category:"flags"},lesotho:{keywords:["ls","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},liberia:{keywords:["lr","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},libya:{keywords:["ly","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},liechtenstein:{keywords:["li","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},lithuania:{keywords:["lt","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},luxembourg:{keywords:["lu","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},macau:{keywords:["macao","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},macedonia:{keywords:["macedonia,","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},madagascar:{keywords:["mg","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},malawi:{keywords:["mw","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},malaysia:{keywords:["my","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},maldives:{keywords:["mv","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1fb}",fitzpatrick_scale:!1,category:"flags"},mali:{keywords:["ml","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},malta:{keywords:["mt","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},marshall_islands:{keywords:["marshall","islands","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},martinique:{keywords:["mq","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f6}",fitzpatrick_scale:!1,category:"flags"},mauritania:{keywords:["mr","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},mauritius:{keywords:["mu","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},mayotte:{keywords:["yt","flag","nation","country","banner"],char:"\u{1f1fe}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},mexico:{keywords:["mx","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1fd}",fitzpatrick_scale:!1,category:"flags"},micronesia:{keywords:["micronesia,","federated","states","flag","nation","country","banner"],char:"\u{1f1eb}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},moldova:{keywords:["moldova,","republic","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},monaco:{keywords:["mc","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},mongolia:{keywords:["mn","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},montenegro:{keywords:["me","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},montserrat:{keywords:["ms","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},morocco:{keywords:["ma","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},mozambique:{keywords:["mz","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},myanmar:{keywords:["mm","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},namibia:{keywords:["na","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},nauru:{keywords:["nr","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},nepal:{keywords:["np","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1f5}",fitzpatrick_scale:!1,category:"flags"},netherlands:{keywords:["nl","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},new_caledonia:{keywords:["new","caledonia","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},new_zealand:{keywords:["new","zealand","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},nicaragua:{keywords:["ni","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},niger:{keywords:["ne","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},nigeria:{keywords:["flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},niue:{keywords:["nu","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},norfolk_island:{keywords:["norfolk","island","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},northern_mariana_islands:{keywords:["northern","mariana","islands","flag","nation","country","banner"],char:"\u{1f1f2}\u{1f1f5}",fitzpatrick_scale:!1,category:"flags"},north_korea:{keywords:["north","korea","nation","flag","country","banner"],char:"\u{1f1f0}\u{1f1f5}",fitzpatrick_scale:!1,category:"flags"},norway:{keywords:["no","flag","nation","country","banner"],char:"\u{1f1f3}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},oman:{keywords:["om_symbol","flag","nation","country","banner"],char:"\u{1f1f4}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},pakistan:{keywords:["pk","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},palau:{keywords:["pw","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},palestinian_territories:{keywords:["palestine","palestinian","territories","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},panama:{keywords:["pa","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},papua_new_guinea:{keywords:["papua","new","guinea","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},paraguay:{keywords:["py","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},peru:{keywords:["pe","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},philippines:{keywords:["ph","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},pitcairn_islands:{keywords:["pitcairn","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},poland:{keywords:["pl","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},portugal:{keywords:["pt","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},puerto_rico:{keywords:["puerto","rico","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},qatar:{keywords:["qa","flag","nation","country","banner"],char:"\u{1f1f6}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},reunion:{keywords:["r\xe9union","flag","nation","country","banner"],char:"\u{1f1f7}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},romania:{keywords:["ro","flag","nation","country","banner"],char:"\u{1f1f7}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},ru:{keywords:["russian","federation","flag","nation","country","banner"],char:"\u{1f1f7}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},rwanda:{keywords:["rw","flag","nation","country","banner"],char:"\u{1f1f7}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},st_barthelemy:{keywords:["saint","barth\xe9lemy","flag","nation","country","banner"],char:"\u{1f1e7}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},st_helena:{keywords:["saint","helena","ascension","tristan","cunha","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},st_kitts_nevis:{keywords:["saint","kitts","nevis","flag","nation","country","banner"],char:"\u{1f1f0}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},st_lucia:{keywords:["saint","lucia","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},st_pierre_miquelon:{keywords:["saint","pierre","miquelon","flag","nation","country","banner"],char:"\u{1f1f5}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},st_vincent_grenadines:{keywords:["saint","vincent","grenadines","flag","nation","country","banner"],char:"\u{1f1fb}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},samoa:{keywords:["ws","flag","nation","country","banner"],char:"\u{1f1fc}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},san_marino:{keywords:["san","marino","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},sao_tome_principe:{keywords:["sao","tome","principe","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},saudi_arabia:{keywords:["flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},senegal:{keywords:["sn","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},serbia:{keywords:["rs","flag","nation","country","banner"],char:"\u{1f1f7}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},seychelles:{keywords:["sc","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},sierra_leone:{keywords:["sierra","leone","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},singapore:{keywords:["sg","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},sint_maarten:{keywords:["sint","maarten","dutch","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1fd}",fitzpatrick_scale:!1,category:"flags"},slovakia:{keywords:["sk","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},slovenia:{keywords:["si","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},solomon_islands:{keywords:["solomon","islands","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1e7}",fitzpatrick_scale:!1,category:"flags"},somalia:{keywords:["so","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},south_africa:{keywords:["south","africa","flag","nation","country","banner"],char:"\u{1f1ff}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},south_georgia_south_sandwich_islands:{keywords:["south","georgia","sandwich","islands","flag","nation","country","banner"],char:"\u{1f1ec}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},kr:{keywords:["south","korea","nation","flag","country","banner"],char:"\u{1f1f0}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},south_sudan:{keywords:["south","sd","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},es:{keywords:["spain","flag","nation","country","banner"],char:"\u{1f1ea}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},sri_lanka:{keywords:["sri","lanka","flag","nation","country","banner"],char:"\u{1f1f1}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},sudan:{keywords:["sd","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1e9}",fitzpatrick_scale:!1,category:"flags"},suriname:{keywords:["sr","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},swaziland:{keywords:["sz","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},sweden:{keywords:["se","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},switzerland:{keywords:["ch","flag","nation","country","banner"],char:"\u{1f1e8}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},syria:{keywords:["syrian","arab","republic","flag","nation","country","banner"],char:"\u{1f1f8}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},taiwan:{keywords:["tw","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},tajikistan:{keywords:["tj","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1ef}",fitzpatrick_scale:!1,category:"flags"},tanzania:{keywords:["tanzania,","united","republic","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},thailand:{keywords:["th","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},timor_leste:{keywords:["timor","leste","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1f1}",fitzpatrick_scale:!1,category:"flags"},togo:{keywords:["tg","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},tokelau:{keywords:["tk","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1f0}",fitzpatrick_scale:!1,category:"flags"},tonga:{keywords:["to","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1f4}",fitzpatrick_scale:!1,category:"flags"},trinidad_tobago:{keywords:["trinidad","tobago","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1f9}",fitzpatrick_scale:!1,category:"flags"},tunisia:{keywords:["tn","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},tr:{keywords:["turkey","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1f7}",fitzpatrick_scale:!1,category:"flags"},turkmenistan:{keywords:["flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},turks_caicos_islands:{keywords:["turks","caicos","islands","flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1e8}",fitzpatrick_scale:!1,category:"flags"},tuvalu:{keywords:["flag","nation","country","banner"],char:"\u{1f1f9}\u{1f1fb}",fitzpatrick_scale:!1,category:"flags"},uganda:{keywords:["ug","flag","nation","country","banner"],char:"\u{1f1fa}\u{1f1ec}",fitzpatrick_scale:!1,category:"flags"},ukraine:{keywords:["ua","flag","nation","country","banner"],char:"\u{1f1fa}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},united_arab_emirates:{keywords:["united","arab","emirates","flag","nation","country","banner"],char:"\u{1f1e6}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},uk:{keywords:["united","kingdom","great","britain","northern","ireland","flag","nation","country","banner","british","UK","english","england","union jack"],char:"\u{1f1ec}\u{1f1e7}",fitzpatrick_scale:!1,category:"flags"},england:{keywords:["flag","english"],char:"\u{1f3f4}\u{e0067}\u{e0062}\u{e0065}\u{e006e}\u{e0067}\u{e007f}",fitzpatrick_scale:!1,category:"flags"},scotland:{keywords:["flag","scottish"],char:"\u{1f3f4}\u{e0067}\u{e0062}\u{e0073}\u{e0063}\u{e0074}\u{e007f}",fitzpatrick_scale:!1,category:"flags"},wales:{keywords:["flag","welsh"],char:"\u{1f3f4}\u{e0067}\u{e0062}\u{e0077}\u{e006c}\u{e0073}\u{e007f}",fitzpatrick_scale:!1,category:"flags"},us:{keywords:["united","states","america","flag","nation","country","banner"],char:"\u{1f1fa}\u{1f1f8}",fitzpatrick_scale:!1,category:"flags"},us_virgin_islands:{keywords:["virgin","islands","us","flag","nation","country","banner"],char:"\u{1f1fb}\u{1f1ee}",fitzpatrick_scale:!1,category:"flags"},uruguay:{keywords:["uy","flag","nation","country","banner"],char:"\u{1f1fa}\u{1f1fe}",fitzpatrick_scale:!1,category:"flags"},uzbekistan:{keywords:["uz","flag","nation","country","banner"],char:"\u{1f1fa}\u{1f1ff}",fitzpatrick_scale:!1,category:"flags"},vanuatu:{keywords:["vu","flag","nation","country","banner"],char:"\u{1f1fb}\u{1f1fa}",fitzpatrick_scale:!1,category:"flags"},vatican_city:{keywords:["vatican","city","flag","nation","country","banner"],char:"\u{1f1fb}\u{1f1e6}",fitzpatrick_scale:!1,category:"flags"},venezuela:{keywords:["ve","bolivarian","republic","flag","nation","country","banner"],char:"\u{1f1fb}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},vietnam:{keywords:["viet","nam","flag","nation","country","banner"],char:"\u{1f1fb}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},wallis_futuna:{keywords:["wallis","futuna","flag","nation","country","banner"],char:"\u{1f1fc}\u{1f1eb}",fitzpatrick_scale:!1,category:"flags"},western_sahara:{keywords:["western","sahara","flag","nation","country","banner"],char:"\u{1f1ea}\u{1f1ed}",fitzpatrick_scale:!1,category:"flags"},yemen:{keywords:["ye","flag","nation","country","banner"],char:"\u{1f1fe}\u{1f1ea}",fitzpatrick_scale:!1,category:"flags"},zambia:{keywords:["zm","flag","nation","country","banner"],char:"\u{1f1ff}\u{1f1f2}",fitzpatrick_scale:!1,category:"flags"},zimbabwe:{keywords:["zw","flag","nation","country","banner"],char:"\u{1f1ff}\u{1f1fc}",fitzpatrick_scale:!1,category:"flags"},united_nations:{keywords:["un","flag","banner"],char:"\u{1f1fa}\u{1f1f3}",fitzpatrick_scale:!1,category:"flags"},pirate_flag:{keywords:["skull","crossbones","flag","banner"],char:"\u{1f3f4}\u200d\u2620\ufe0f",fitzpatrick_scale:!1,category:"flags"}}); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/emoticons/plugin.min.js b/public/plugins/tinymce/plugins/emoticons/plugin.min.js new file mode 100644 index 000000000..3323c94a7 --- /dev/null +++ b/public/plugins/tinymce/plugins/emoticons/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=t=>e=>t===e,o=e(null),n=e(void 0),s=()=>{},r=()=>!1;class a{constructor(t,e){this.tag=t,this.value=e}static some(t){return new a(!0,t)}static none(){return a.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?a.some(t(this.value)):a.none()}bind(t){return this.tag?t(this.value):a.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:a.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return null==t?a.none():a.some(t)}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}a.singletonNone=new a(!1);const i=(t,e)=>{const o=t.length,n=new Array(o);for(let s=0;s{let e=t;return{get:()=>e,set:t=>{e=t}}},c=Object.keys,u=Object.hasOwnProperty,g=(t,e)=>{const o=c(t);for(let n=0,s=o.length;nu.call(t,e),h=(d=(t,e)=>e,(...t)=>{if(0===t.length)throw new Error("Can't merge zero objects");const e={};for(let o=0;o{const t=(t=>{const e=l(a.none()),o=()=>e.get().each(t);return{clear:()=>{o(),e.set(a.none())},isSet:()=>e.get().isSome(),get:()=>e.get(),set:t=>{o(),e.set(a.some(t))}}})(s);return{...t,on:e=>t.get().each(e)}},v=(t,e,o=0,s)=>{const r=t.indexOf(e,o);return-1!==r&&(!!n(s)||r+e.length<=s)};var y=tinymce.util.Tools.resolve("tinymce.Resource");const f=t=>e=>e.options.get(t),b=f("emoticons_database"),w=f("emoticons_database_url"),_=f("emoticons_database_id"),j=f("emoticons_append"),C=f("emoticons_images_url"),k="All",A={symbols:"Symbols",people:"People",animals_and_nature:"Animals and Nature",food_and_drink:"Food and Drink",activity:"Activity",travel_and_places:"Travel and Places",objects:"Objects",flags:"Flags",user:"User Defined"},O=(t,e)=>m(t,e)?t[e]:e,x=t=>{const e=j(t);return o=t=>({keywords:[],category:"user",...t}),((t,e)=>{const o={};return g(t,((t,n)=>{const s=e(t,n);o[s.k]=s.v})),o})(e,((t,e)=>({k:e,v:o(t)})));var o},L=(t,e)=>v(t.title.toLowerCase(),e)||((t,o)=>{for(let o=0,s=t.length;o{const n=[],s=e.toLowerCase(),a=o.fold((()=>r),(t=>e=>e>=t));for(let o=0;o{const n={pattern:"",results:T(e.listAll(),"",a.some(300))},s=l(k),r=((t,e)=>{let n=null;const s=()=>{o(n)||(clearTimeout(n),n=null)};return{cancel:s,throttle:(...e)=>{s(),n=setTimeout((()=>{n=null,t.apply(null,e)}),200)}}})((t=>{(t=>{const o=t.getData(),n=s.get(),r=e.listCategory(n),i=T(r,o.pattern,n===k?a.some(300):a.none());t.setData({results:i})})(t)})),c={label:"Search",type:"input",name:D},u={type:"collection",name:"results"},g=()=>({title:"Emojis",size:"normal",body:{type:"tabpanel",tabs:i(e.listCategories(),(t=>({title:t,name:t,items:[c,u]})))},initialData:n,onTabChange:(t,e)=>{s.set(e.newTabName),r.throttle(t)},onChange:r.throttle,onAction:(e,o)=>{"results"===o.name&&(((t,e)=>{t.insertContent(e)})(t,o.value),e.close())},buttons:[{type:"cancel",text:"Close",primary:!0}]}),m=t.windowManager.open(g());m.focus(D),e.hasLoaded()||(m.block("Loading emojis..."),e.waitForLoad().then((()=>{m.redial(g()),r.throttle(m),m.focus(D),m.unblock()})).catch((t=>{m.redial({title:"Emojis",body:{type:"panel",items:[{type:"alertbanner",level:"error",icon:"warning",text:"Could not load emojis"}]},buttons:[{type:"cancel",text:"Close",primary:!0}],initialData:{pattern:"",results:[]}}),m.focus(D),m.unblock()})))};t.add("emoticons",((t,e)=>{((t,e)=>{const o=t.options.register;o("emoticons_database",{processor:"string",default:"emojis"}),o("emoticons_database_url",{processor:"string",default:`${e}/js/${b(t)}${t.suffix}.js`}),o("emoticons_database_id",{processor:"string",default:"tinymce.plugins.emoticons"}),o("emoticons_append",{processor:"object",default:{}}),o("emoticons_images_url",{processor:"string",default:"https://twemoji.maxcdn.com/v/13.0.1/72x72/"})})(t,e);const o=((t,e,o)=>{const n=p(),s=p(),r=C(t),i=t=>{return o="=o.length&&e.substr(0,0+o.length)===o?t.char.replace(/src="([^"]+)"/,((t,e)=>`src="${r}${e}"`)):t.char;var e,o};t.on("init",(()=>{y.load(o,e).then((e=>{const o=x(t);(t=>{const e={},o=[];g(t,((t,n)=>{const s={title:n,keywords:t.keywords,char:i(t),category:O(A,t.category)},r=void 0!==e[s.category]?e[s.category]:[];e[s.category]=r.concat([s]),o.push(s)})),n.set(e),s.set(o)})(h(e,o))}),(t=>{console.log(`Failed to load emojis: ${t}`),n.set({}),s.set([])}))}));const l=()=>s.get().getOr([]),u=()=>n.isSet()&&s.isSet();return{listCategories:()=>[k].concat(c(n.get().getOr({}))),hasLoaded:u,waitForLoad:()=>u()?Promise.resolve(!0):new Promise(((t,o)=>{let n=15;const s=setInterval((()=>{u()?(clearInterval(s),t(!0)):(n--,n<0&&(console.log("Could not load emojis from url: "+e),clearInterval(s),o(!1)))}),100)})),listAll:l,listCategory:t=>t===k?l():n.get().bind((e=>a.from(e[t]))).getOr([])}})(t,w(t),_(t));((t,e)=>{t.addCommand("mceEmoticons",(()=>E(t,e)))})(t,o),(t=>{const e=()=>t.execCommand("mceEmoticons");t.ui.registry.addButton("emoticons",{tooltip:"Emojis",icon:"emoji",onAction:e}),t.ui.registry.addMenuItem("emoticons",{text:"Emojis...",icon:"emoji",onAction:e})})(t),((t,e)=>{t.ui.registry.addAutocompleter("emoticons",{trigger:":",columns:"auto",minChars:2,fetch:(t,o)=>e.waitForLoad().then((()=>{const n=e.listAll();return T(n,t,a.some(o))})),onAction:(e,o,n)=>{t.selection.setRng(o),t.insertContent(n),e.hide()}})})(t,o),(t=>{t.on("PreInit",(()=>{t.parser.addAttributeFilter("data-emoticon",(t=>{((t,e)=>{for(let e=0,n=t.length;e{let t=e;return{get:()=>t,set:e=>{t=e}}};var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const n=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=r=e,(o=String).prototype.isPrototypeOf(n)||(null===(s=r.constructor)||void 0===s?void 0:s.name)===o.name)?"string":t;var n,r,o,s})(t)===e,r=e=>t=>typeof t===e,o=e=>t=>e===t,s=n("string"),i=n("array"),l=o(null),a=r("boolean"),c=o(void 0),u=e=>!(e=>null==e)(e),d=r("function"),m=r("number"),h=()=>{},g=e=>()=>e;function p(e,...t){return(...n)=>{const r=t.concat(n);return e.apply(null,r)}}const f=g(!1),v=g(!0);class w{constructor(e,t){this.tag=e,this.value=t}static some(e){return new w(!0,e)}static none(){return w.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?w.some(e(this.value)):w.none()}bind(e){return this.tag?e(this.value):w.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:w.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return u(e)?w.some(e):w.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}w.singletonNone=new w(!1);const y=t=>{const n=e(w.none()),r=()=>n.get().each(t);return{clear:()=>{r(),n.set(w.none())},isSet:()=>n.get().isSome(),get:()=>n.get(),set:e=>{r(),n.set(w.some(e))}}},b=()=>y((e=>e.unbind())),S=Array.prototype.push,x=(e,t)=>{const n=e.length,r=new Array(n);for(let o=0;o{for(let n=0,r=e.length;n{const n=[];for(let r=0,o=e.length;r((e,t,n)=>{for(let r=0,o=e.length;r{const o=e.indexOf(t,n);return-1!==o&&(!!c(r)||o+t.length<=r)},C=e=>void 0!==e.style&&d(e.style.getPropertyValue),A=e=>{if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}},R=A;"undefined"!=typeof window?window:Function("return this;")();const L=e=>t=>(e=>e.dom.nodeType)(t)===e,M=L(1),N=L(3),P=L(9),D=L(11),W=(e,t)=>{const n=e.dom;if(1!==n.nodeType)return!1;{const e=n;if(void 0!==e.matches)return e.matches(t);if(void 0!==e.msMatchesSelector)return e.msMatchesSelector(t);if(void 0!==e.webkitMatchesSelector)return e.webkitMatchesSelector(t);if(void 0!==e.mozMatchesSelector)return e.mozMatchesSelector(t);throw new Error("Browser lacks native selectors")}},q=e=>R(e.dom.ownerDocument),H=e=>x(e.dom.childNodes,R),I=d(Element.prototype.attachShadow)&&d(Node.prototype.getRootNode),B=g(I),V=I?e=>R(e.dom.getRootNode()):e=>P(e)?e:q(e),_=e=>{const t=V(e);return D(n=t)&&u(n.dom.host)?w.some(t):w.none();var n},j=e=>R(e.dom.host),z=e=>{const t=N(e)?e.dom.parentNode:e.dom;if(null==t||null===t.ownerDocument)return!1;const n=t.ownerDocument;return _(R(t)).fold((()=>n.body.contains(t)),(r=z,o=j,e=>r(o(e))));var r,o},$=(e,t)=>{const n=e.dom.getAttribute(t);return null===n?void 0:n},U=(e,t)=>{e.dom.removeAttribute(t)},K=(e,t)=>{const n=e.dom;((e,t)=>{const n=T(e);for(let r=0,o=n.length;r{((e,t,n)=>{if(!s(n))throw console.error("Invalid call to CSS.set. Property ",t,":: Value ",n,":: Element ",e),new Error("CSS value must be a string: "+n);C(e)&&e.style.setProperty(t,n)})(n,t,e)}))},X=e=>{const t=R((e=>{if(B()&&u(e.target)){const t=R(e.target);if(M(t)&&u(t.dom.shadowRoot)&&e.composed&&e.composedPath){const t=e.composedPath();if(t)return((e,t)=>0e.stopPropagation(),r=()=>e.preventDefault(),o=(s=r,i=n,(...e)=>s(i.apply(null,e)));var s,i;return((e,t,n,r,o,s,i)=>({target:e,x:t,y:n,stop:r,prevent:o,kill:s,raw:i}))(t,e.clientX,e.clientY,n,r,o,e)},Y=(e,t,n,r)=>{e.dom.removeEventListener(t,n,r)},G=v,J=(e,t,n)=>((e,t,n,r)=>((e,t,n,r,o)=>{const s=((e,t)=>n=>{e(n)&&t(X(n))})(n,r);return e.dom.addEventListener(t,s,o),{unbind:p(Y,e,t,s,o)}})(e,t,n,r,!1))(e,t,G,n),Q=()=>Z(0,0),Z=(e,t)=>({major:e,minor:t}),ee={nu:Z,detect:(e,t)=>{const n=String(t).toLowerCase();return 0===e.length?Q():((e,t)=>{const n=((e,t)=>{for(let n=0;nNumber(t.replace(n,"$"+e));return Z(r(1),r(2))})(e,n)},unknown:Q},te=(e,t)=>{const n=String(t).toLowerCase();return O(e,(e=>e.search(n)))},ne=/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,re=e=>t=>k(t,e),oe=[{name:"Edge",versionRegexes:[/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],search:e=>k(e,"edge/")&&k(e,"chrome")&&k(e,"safari")&&k(e,"applewebkit")},{name:"Chromium",brand:"Chromium",versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/,ne],search:e=>k(e,"chrome")&&!k(e,"chromeframe")},{name:"IE",versionRegexes:[/.*?msie\ ?([0-9]+)\.([0-9]+).*/,/.*?rv:([0-9]+)\.([0-9]+).*/],search:e=>k(e,"msie")||k(e,"trident")},{name:"Opera",versionRegexes:[ne,/.*?opera\/([0-9]+)\.([0-9]+).*/],search:re("opera")},{name:"Firefox",versionRegexes:[/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],search:re("firefox")},{name:"Safari",versionRegexes:[ne,/.*?cpu os ([0-9]+)_([0-9]+).*/],search:e=>(k(e,"safari")||k(e,"mobile/"))&&k(e,"applewebkit")}],se=[{name:"Windows",search:re("win"),versionRegexes:[/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]},{name:"iOS",search:e=>k(e,"iphone")||k(e,"ipad"),versionRegexes:[/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,/.*cpu os ([0-9]+)_([0-9]+).*/,/.*cpu iphone os ([0-9]+)_([0-9]+).*/]},{name:"Android",search:re("android"),versionRegexes:[/.*?android\ ?([0-9]+)\.([0-9]+).*/]},{name:"macOS",search:re("mac os x"),versionRegexes:[/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]},{name:"Linux",search:re("linux"),versionRegexes:[]},{name:"Solaris",search:re("sunos"),versionRegexes:[]},{name:"FreeBSD",search:re("freebsd"),versionRegexes:[]},{name:"ChromeOS",search:re("cros"),versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/]}],ie={browsers:g(oe),oses:g(se)},le="Edge",ae="Chromium",ce="Opera",ue="Firefox",de="Safari",me=e=>{const t=e.current,n=e.version,r=e=>()=>t===e;return{current:t,version:n,isEdge:r(le),isChromium:r(ae),isIE:r("IE"),isOpera:r(ce),isFirefox:r(ue),isSafari:r(de)}},he=()=>me({current:void 0,version:ee.unknown()}),ge=me,pe=(g(le),g(ae),g("IE"),g(ce),g(ue),g(de),"Windows"),fe="Android",ve="Linux",we="macOS",ye="Solaris",be="FreeBSD",Se="ChromeOS",xe=e=>{const t=e.current,n=e.version,r=e=>()=>t===e;return{current:t,version:n,isWindows:r(pe),isiOS:r("iOS"),isAndroid:r(fe),isMacOS:r(we),isLinux:r(ve),isSolaris:r(ye),isFreeBSD:r(be),isChromeOS:r(Se)}},Ee=()=>xe({current:void 0,version:ee.unknown()}),Fe=xe,Oe=(g(pe),g("iOS"),g(fe),g(ve),g(we),g(ye),g(be),g(Se),(e,t,n)=>{const r=ie.browsers(),o=ie.oses(),s=t.bind((e=>((e,t)=>((e,t)=>{for(let n=0;n{const n=t.brand.toLowerCase();return O(e,(e=>{var t;return n===(null===(t=e.brand)||void 0===t?void 0:t.toLowerCase())})).map((e=>({current:e.name,version:ee.nu(parseInt(t.version,10),0)})))})))(r,e))).orThunk((()=>((e,t)=>te(e,t).map((e=>{const n=ee.detect(e.versionRegexes,t);return{current:e.name,version:n}})))(r,e))).fold(he,ge),i=((e,t)=>te(e,t).map((e=>{const n=ee.detect(e.versionRegexes,t);return{current:e.name,version:n}})))(o,e).fold(Ee,Fe),l=((e,t,n,r)=>{const o=e.isiOS()&&!0===/ipad/i.test(n),s=e.isiOS()&&!o,i=e.isiOS()||e.isAndroid(),l=i||r("(pointer:coarse)"),a=o||!s&&i&&r("(min-device-width:768px)"),c=s||i&&!a,u=t.isSafari()&&e.isiOS()&&!1===/safari/i.test(n),d=!c&&!a&&!u;return{isiPad:g(o),isiPhone:g(s),isTablet:g(a),isPhone:g(c),isTouch:g(l),isAndroid:e.isAndroid,isiOS:e.isiOS,isWebView:g(u),isDesktop:g(d)}})(i,s,e,n);return{browser:s,os:i,deviceType:l}}),Te=e=>window.matchMedia(e).matches;let ke=(e=>{let t,n=!1;return(...r)=>(n||(n=!0,t=e.apply(null,r)),t)})((()=>Oe(navigator.userAgent,w.from(navigator.userAgentData),Te)));const Ce=(e,t)=>({left:e,top:t,translate:(n,r)=>Ce(e+n,t+r)}),Ae=Ce,Re=e=>{const t=void 0===e?window:e;return ke().browser.isFirefox()?w.none():w.from(t.visualViewport)},Le=(e,t,n,r)=>({x:e,y:t,width:n,height:r,right:e+n,bottom:t+r}),Me=e=>{const t=void 0===e?window:e,n=t.document,r=(e=>{const t=void 0!==e?e.dom:document,n=t.body.scrollLeft||t.documentElement.scrollLeft,r=t.body.scrollTop||t.documentElement.scrollTop;return Ae(n,r)})(R(n));return Re(t).fold((()=>{const e=t.document.documentElement,n=e.clientWidth,o=e.clientHeight;return Le(r.left,r.top,n,o)}),(e=>Le(Math.max(e.pageLeft,r.left),Math.max(e.pageTop,r.top),e.width,e.height)))},Ne=(e,t,n)=>Re(n).map((n=>{const r=e=>t(X(e));return n.addEventListener(e,r),{unbind:()=>n.removeEventListener(e,r)}})).getOrThunk((()=>({unbind:h})));var Pe=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),De=tinymce.util.Tools.resolve("tinymce.Env");const We=(e,t)=>{e.dispatch("FullscreenStateChanged",{state:t}),e.dispatch("ResizeEditor")},qe=("fullscreen_native",e=>e.options.get("fullscreen_native"));const He=e=>{return e.dom===(void 0!==(t=q(e).dom).fullscreenElement?t.fullscreenElement:void 0!==t.msFullscreenElement?t.msFullscreenElement:void 0!==t.webkitFullscreenElement?t.webkitFullscreenElement:null);var t},Ie=(e,t,n)=>((e,t,n)=>F(((e,t)=>{const n=d(t)?t:f;let r=e.dom;const o=[];for(;null!==r.parentNode&&void 0!==r.parentNode;){const e=r.parentNode,t=R(e);if(o.push(t),!0===n(t))break;r=e}return o})(e,n),t))(e,(e=>W(e,t)),n),Be=(e,t)=>((e,n)=>{return F((e=>w.from(e.dom.parentNode).map(R))(r=e).map(H).map((e=>F(e,(e=>{return t=e,!(r.dom===t.dom);var t})))).getOr([]),(e=>W(e,t)));var r})(e),Ve="data-ephox-mobile-fullscreen-style",_e="position:absolute!important;",je="top:0!important;left:0!important;margin:0!important;padding:0!important;width:100%!important;height:100%!important;overflow:visible!important;",ze=De.os.isAndroid(),$e=e=>{const t=((e,t)=>{const n=e.dom,r=window.getComputedStyle(n).getPropertyValue(t);return""!==r||z(e)?r:((e,t)=>C(e)?e.style.getPropertyValue(t):"")(n,t)})(e,"background-color");return void 0!==t&&""!==t?"background-color:"+t+"!important":"background-color:rgb(255,255,255)!important;"},Ue=Pe.DOM,Ke=Re().fold((()=>({bind:h,unbind:h})),(e=>{const t=(()=>{const e=y(h);return{...e,on:t=>e.get().each(t)}})(),n=b(),r=b(),o=((e,t)=>{let n=null;return{cancel:()=>{l(n)||(clearTimeout(n),n=null)},throttle:(...t)=>{l(n)&&(n=setTimeout((()=>{n=null,e.apply(null,t)}),50))}}})((()=>{document.body.scrollTop=0,document.documentElement.scrollTop=0,window.requestAnimationFrame((()=>{t.on((t=>K(t,{top:e.offsetTop+"px",left:e.offsetLeft+"px",height:e.height+"px",width:e.width+"px"})))}))}));return{bind:e=>{t.set(e),o.throttle(),n.set(Ne("resize",o.throttle)),r.set(Ne("scroll",o.throttle))},unbind:()=>{t.on((()=>{n.clear(),r.clear()})),t.clear()}}})),Xe=(e,t)=>{const n=document.body,r=document.documentElement,o=e.getContainer(),l=R(o),c=(e=>{const t=R(e.getElement());return _(t).map(j).getOrThunk((()=>(e=>{const t=e.dom.body;if(null==t)throw new Error("Body is not available yet");return R(t)})(q(t))))})(e),u=t.get(),d=R(e.getBody()),h=De.deviceType.isTouch(),g=o.style,p=e.iframeElement,f=null==p?void 0:p.style,v=e=>{e(n,"tox-fullscreen"),e(r,"tox-fullscreen"),e(o,"tox-fullscreen"),_(l).map((e=>j(e).dom)).each((t=>{e(t,"tox-fullscreen"),e(t,"tox-shadowhost")}))},y=()=>{h&&(e=>{const t=((e,t)=>{const n=document;return 1!==(r=n).nodeType&&9!==r.nodeType&&11!==r.nodeType||0===r.childElementCount?[]:x(n.querySelectorAll(e),R);var r})("["+Ve+"]");E(t,(t=>{const n=$(t,Ve);n&&"no-styles"!==n?K(t,e.parseStyle(n)):U(t,"style"),U(t,Ve)}))})(e.dom),v(Ue.removeClass),Ke.unbind(),w.from(t.get()).each((e=>e.fullscreenChangeHandler.unbind()))};if(u)u.fullscreenChangeHandler.unbind(),qe(e)&&He(c)&&(e=>{const t=e.dom;t.exitFullscreen?t.exitFullscreen():t.msExitFullscreen?t.msExitFullscreen():t.webkitCancelFullScreen&&t.webkitCancelFullScreen()})(q(c)),f.width=u.iframeWidth,f.height=u.iframeHeight,g.width=u.containerWidth,g.height=u.containerHeight,g.top=u.containerTop,g.left=u.containerLeft,y(),b=u.scrollPos,window.scrollTo(b.x,b.y),t.set(null),We(e,!1),e.off("remove",y);else{const n=J(q(c),void 0!==document.fullscreenElement?"fullscreenchange":void 0!==document.msFullscreenElement?"MSFullscreenChange":void 0!==document.webkitFullscreenElement?"webkitfullscreenchange":"fullscreenchange",(n=>{qe(e)&&(He(c)||null===t.get()||Xe(e,t))})),r={scrollPos:Me(window),containerWidth:g.width,containerHeight:g.height,containerTop:g.top,containerLeft:g.left,iframeWidth:f.width,iframeHeight:f.height,fullscreenChangeHandler:n};h&&((e,t,n)=>{const r=t=>n=>{const r=$(n,"style"),o=void 0===r?"no-styles":r.trim();o!==t&&(((e,t,n)=>{((e,t,n)=>{if(!(s(n)||a(n)||m(n)))throw console.error("Invalid call to Attribute.set. Key ",t,":: Value ",n,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(t,n+"")})(e.dom,t,n)})(n,Ve,o),K(n,e.parseStyle(t)))},o=Ie(t,"*"),l=(e=>{const t=[];for(let n=0,r=e.length;nBe(e,"*:not(.tox-silver-sink)")))),c=$e(n);E(l,r("display:none!important;")),E(o,r(_e+je+c)),r((!0===ze?"":_e)+je+c)(t)})(e.dom,l,d),f.width=f.height="100%",g.width=g.height="",v(Ue.addClass),Ke.bind(l),e.on("remove",y),t.set(r),qe(e)&&(e=>{const t=e.dom;t.requestFullscreen?t.requestFullscreen():t.msRequestFullscreen?t.msRequestFullscreen():t.webkitRequestFullScreen&&t.webkitRequestFullScreen()})(c),We(e,!0)}var b},Ye=(e,t)=>n=>{n.setActive(null!==t.get());const r=e=>n.setActive(e.state);return e.on("FullscreenStateChanged",r),()=>e.off("FullscreenStateChanged",r)};t.add("fullscreen",(t=>{const n=e(null);return t.inline||((e=>{(0,e.options.register)("fullscreen_native",{processor:"boolean",default:!1})})(t),((e,t)=>{e.addCommand("mceFullScreen",(()=>{Xe(e,t)}))})(t,n),((e,t)=>{const n=()=>e.execCommand("mceFullScreen");e.ui.registry.addToggleMenuItem("fullscreen",{text:"Fullscreen",icon:"fullscreen",shortcut:"Meta+Shift+F",onAction:n,onSetup:Ye(e,t)}),e.ui.registry.addToggleButton("fullscreen",{tooltip:"Fullscreen",icon:"fullscreen",onAction:n,onSetup:Ye(e,t)})})(t,n),t.addShortcut("Meta+Shift+F","","mceFullScreen")),(e=>({isFullscreen:()=>null!==e.get()}))(n)}))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/help/plugin.min.js b/public/plugins/tinymce/plugins/help/plugin.min.js new file mode 100644 index 000000000..5f86fe5b0 --- /dev/null +++ b/public/plugins/tinymce/plugins/help/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");let t=0;const n=e=>{const n=(new Date).getTime(),a=Math.floor(1e9*Math.random());return t++,e+"_"+a+t+String(n)},a=e=>t=>t.options.get(e),o=a("help_tabs"),i=a("forced_plugins"),r=("string",e=>"string"===(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=a=e,(o=String).prototype.isPrototypeOf(n)||(null===(i=a.constructor)||void 0===i?void 0:i.name)===o.name)?"string":t;var n,a,o,i})(e));const s=(void 0,e=>undefined===e);const l=e=>"function"==typeof e,c=(!1,()=>false);class u{constructor(e,t){this.tag=e,this.value=t}static some(e){return new u(!0,e)}static none(){return u.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?u.some(e(this.value)):u.none()}bind(e){return this.tag?e(this.value):u.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:u.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return null==e?u.none():u.some(e)}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}u.singletonNone=new u(!1);const m=Array.prototype.slice,h=Array.prototype.indexOf,p=(e,t)=>{const n=e.length,a=new Array(n);for(let o=0;o{const n=[];for(let a=0,o=e.length;a{const n=m.call(e,0);return n.sort(t),n},y=Object.keys,b=Object.hasOwnProperty,k=(e,t)=>b.call(e,t);var v=tinymce.util.Tools.resolve("tinymce.Env");const f=e=>{const t=v.os.isMacOS()||v.os.isiOS(),n=t?{alt:"⌥",ctrl:"⌃",shift:"⇧",meta:"⌘",access:"⌃⌥"}:{meta:"Ctrl ",access:"Shift + Alt "},a=e.split("+"),o=p(a,(e=>{const t=e.toLowerCase().trim();return k(n,t)?n[t]:e}));return t?o.join("").replace(/\s/,""):o.join("+")},w=[{shortcuts:["Meta + B"],action:"Bold"},{shortcuts:["Meta + I"],action:"Italic"},{shortcuts:["Meta + U"],action:"Underline"},{shortcuts:["Meta + A"],action:"Select all"},{shortcuts:["Meta + Y","Meta + Shift + Z"],action:"Redo"},{shortcuts:["Meta + Z"],action:"Undo"},{shortcuts:["Access + 1"],action:"Heading 1"},{shortcuts:["Access + 2"],action:"Heading 2"},{shortcuts:["Access + 3"],action:"Heading 3"},{shortcuts:["Access + 4"],action:"Heading 4"},{shortcuts:["Access + 5"],action:"Heading 5"},{shortcuts:["Access + 6"],action:"Heading 6"},{shortcuts:["Access + 7"],action:"Paragraph"},{shortcuts:["Access + 8"],action:"Div"},{shortcuts:["Access + 9"],action:"Address"},{shortcuts:["Alt + 0"],action:"Open help dialog"},{shortcuts:["Alt + F9"],action:"Focus to menubar"},{shortcuts:["Alt + F10"],action:"Focus to toolbar"},{shortcuts:["Alt + F11"],action:"Focus to element path"},{shortcuts:["Ctrl + F9"],action:"Focus to contextual toolbar"},{shortcuts:["Shift + Enter"],action:"Open popup menu for split buttons"},{shortcuts:["Meta + K"],action:"Insert link (if link plugin activated)"},{shortcuts:["Meta + S"],action:"Save (if save plugin activated)"},{shortcuts:["Meta + F"],action:"Find (if searchreplace plugin activated)"},{shortcuts:["Meta + Shift + F"],action:"Switch to or from fullscreen mode"}],A=()=>({name:"shortcuts",title:"Handy Shortcuts",items:[{type:"table",header:["Action","Shortcut"],cells:p(w,(e=>{const t=p(e.shortcuts,f).join(" or ");return[e.action,t]}))}]});var x=tinymce.util.Tools.resolve("tinymce.util.I18n");const T=p([{key:"advlist",name:"Advanced List"},{key:"anchor",name:"Anchor"},{key:"autolink",name:"Autolink"},{key:"autoresize",name:"Autoresize"},{key:"autosave",name:"Autosave"},{key:"charmap",name:"Character Map"},{key:"code",name:"Code"},{key:"codesample",name:"Code Sample"},{key:"colorpicker",name:"Color Picker"},{key:"directionality",name:"Directionality"},{key:"emoticons",name:"Emoticons"},{key:"fullscreen",name:"Full Screen"},{key:"help",name:"Help"},{key:"image",name:"Image"},{key:"importcss",name:"Import CSS"},{key:"insertdatetime",name:"Insert Date/Time"},{key:"link",name:"Link"},{key:"lists",name:"Lists"},{key:"media",name:"Media"},{key:"nonbreaking",name:"Nonbreaking"},{key:"pagebreak",name:"Page Break"},{key:"preview",name:"Preview"},{key:"quickbars",name:"Quick Toolbars"},{key:"save",name:"Save"},{key:"searchreplace",name:"Search and Replace"},{key:"table",name:"Table"},{key:"template",name:"Template"},{key:"textcolor",name:"Text Color"},{key:"visualblocks",name:"Visual Blocks"},{key:"visualchars",name:"Visual Characters"},{key:"wordcount",name:"Word Count"},{key:"a11ychecker",name:"Accessibility Checker",type:"premium"},{key:"advcode",name:"Advanced Code Editor",type:"premium"},{key:"advtable",name:"Advanced Tables",type:"premium"},{key:"casechange",name:"Case Change",type:"premium"},{key:"checklist",name:"Checklist",type:"premium"},{key:"editimage",name:"Enhanced Image Editing",type:"premium"},{key:"footnotes",name:"Footnotes",type:"premium"},{key:"typography",name:"Advanced Typography",type:"premium"},{key:"mediaembed",name:"Enhanced Media Embed",type:"premium",slug:"introduction-to-mediaembed"},{key:"export",name:"Export",type:"premium"},{key:"formatpainter",name:"Format Painter",type:"premium"},{key:"inlinecss",name:"Inline CSS",type:"premium"},{key:"linkchecker",name:"Link Checker",type:"premium"},{key:"mentions",name:"Mentions",type:"premium"},{key:"mergetags",name:"Merge Tags",type:"premium"},{key:"pageembed",name:"Page Embed",type:"premium"},{key:"permanentpen",name:"Permanent Pen",type:"premium"},{key:"powerpaste",name:"PowerPaste",type:"premium",slug:"introduction-to-powerpaste"},{key:"rtc",name:"Real-Time Collaboration",type:"premium",slug:"rtc-introduction"},{key:"tinymcespellchecker",name:"Spell Checker Pro",type:"premium",slug:"introduction-to-tiny-spellchecker"},{key:"autocorrect",name:"Spelling Autocorrect",type:"premium"},{key:"tableofcontents",name:"Table of Contents",type:"premium"},{key:"tinycomments",name:"Tiny Comments",type:"premium",slug:"introduction-to-tiny-comments"},{key:"tinydrive",name:"Tiny Drive",type:"premium",slug:"tinydrive-introduction"}],(e=>({...e,type:e.type||"opensource",slug:e.slug||e.key}))),C=e=>{const t=e=>`${e.name}`,n=(e,n)=>{return(a=T,o=e=>e.key===n,((e,t,n)=>{for(let a=0,o=e.length;a((e,n)=>{const a=e.plugins[n].getMetadata;if(l(a)){const e=a();return{name:e.name,html:t(e)}}return{name:n,html:n}})(e,n)),(e=>{const n="premium"===e.type?`${e.name}*`:e.name;return{name:n,html:t({name:n,url:`https://www.tiny.cloud/docs/tinymce/6/${e.slug}/`})}}));var a,o},a=e=>{const t=(e=>{const t=y(e.plugins),n=i(e);return s(n)?t:d(t,(e=>!(((e,t)=>h.call(e,t))(n,e)>-1)))})(e),a=g(p(t,(t=>n(e,t))),((e,t)=>e.name.localeCompare(t.name))),o=p(a,(e=>"
  • "+e.html+"
  • ")),r=o.length,l=o.join("");return"

    "+x.translate(["Plugins installed ({0}):",r])+"

      "+l+"
    "},o={type:"htmlpanel",presets:"document",html:[(e=>null==e?"":'
    '+a(e)+"
    ")(e),(()=>{const e=d(T,(({type:e})=>"premium"===e)),t=g(p(e,(e=>e.name)),((e,t)=>e.localeCompare(t))),n=p(t,(e=>`
  • ${e}
  • `)).join("");return'

    '+x.translate("Premium plugins:")+"

    "})()].join("")};return{name:"plugins",title:"Plugins",items:[o]}};var M=tinymce.util.Tools.resolve("tinymce.EditorManager");const S=(e,t)=>()=>{const{tabs:a,names:i}=((e,t)=>{const a=A(),i={name:"keyboardnav",title:"Keyboard Navigation",items:[{type:"htmlpanel",presets:"document",html:"

    Editor UI keyboard navigation

    \n\n

    Activating keyboard navigation

    \n\n

    The sections of the outer UI of the editor - the menubar, toolbar, sidebar and footer - are all keyboard navigable. As such, there are multiple ways to activate keyboard navigation:

    \n
      \n
    • Focus the menubar: Alt + F9 (Windows) or ⌥F9 (MacOS)
    • \n
    • Focus the toolbar: Alt + F10 (Windows) or ⌥F10 (MacOS)
    • \n
    • Focus the footer: Alt + F11 (Windows) or ⌥F11 (MacOS)
    • \n
    \n\n

    Focusing the menubar or toolbar will start keyboard navigation at the first item in the menubar or toolbar, which will be highlighted with a gray background. Focusing the footer will start keyboard navigation at the first item in the element path, which will be highlighted with an underline.

    \n\n

    Moving between UI sections

    \n\n

    When keyboard navigation is active, pressing tab will move the focus to the next major section of the UI, where applicable. These sections are:

    \n
      \n
    • the menubar
    • \n
    • each group of the toolbar
    • \n
    • the sidebar
    • \n
    • the element path in the footer
    • \n
    • the wordcount toggle button in the footer
    • \n
    • the branding link in the footer
    • \n
    • the editor resize handle in the footer
    • \n
    \n\n

    Pressing shift + tab will move backwards through the same sections, except when moving from the footer to the toolbar. Focusing the element path then pressing shift + tab will move focus to the first toolbar group, not the last.

    \n\n

    Moving within UI sections

    \n\n

    Keyboard navigation within UI sections can usually be achieved using the left and right arrow keys. This includes:

    \n
      \n
    • moving between menus in the menubar
    • \n
    • moving between buttons in a toolbar group
    • \n
    • moving between items in the element path
    • \n
    \n\n

    In all these UI sections, keyboard navigation will cycle within the section. For example, focusing the last button in a toolbar group then pressing right arrow will move focus to the first item in the same toolbar group.

    \n\n

    Executing buttons

    \n\n

    To execute a button, navigate the selection to the desired button and hit space or enter.

    \n\n

    Opening, navigating and closing menus

    \n\n

    When focusing a menubar button or a toolbar button with a menu, pressing space, enter or down arrow will open the menu. When the menu opens the first item will be selected. To move up or down the menu, press the up or down arrow key respectively. This is the same for submenus, which can also be opened and closed using the left and right arrow keys.

    \n\n

    To close any active menu, hit the escape key. When a menu is closed the selection will be restored to its previous selection. This also works for closing submenus.

    \n\n

    Context toolbars and menus

    \n\n

    To focus an open context toolbar such as the table context toolbar, press Ctrl + F9 (Windows) or ⌃F9 (MacOS).

    \n\n

    Context toolbar navigation is the same as toolbar navigation, and context menu navigation is the same as standard menu navigation.

    \n\n

    Dialog navigation

    \n\n

    There are two types of dialog UIs in TinyMCE: tabbed dialogs and non-tabbed dialogs.

    \n\n

    When a non-tabbed dialog is opened, the first interactive component in the dialog will be focused. Users can navigate between interactive components by pressing tab. This includes any footer buttons. Navigation will cycle back to the first dialog component if tab is pressed while focusing the last component in the dialog. Pressing shift + tab will navigate backwards.

    \n\n

    When a tabbed dialog is opened, the first button in the tab menu is focused. Pressing tab will navigate to the first interactive component in that tab, and will cycle through the tab\u2019s components, the footer buttons, then back to the tab button. To switch to another tab, focus the tab button for the current tab, then use the arrow keys to cycle through the tab buttons.

    "}]},s=C(e),l=(()=>{var e,t;const n='TinyMCE '+(e=M.majorVersion,t=M.minorVersion,(0===e.indexOf("@")?"X.X.X":e+"."+t)+"");return{name:"versions",title:"Version",items:[{type:"htmlpanel",html:"

    "+x.translate(["You are using {0}",n])+"

    ",presets:"document"}]}})(),c={[a.name]:a,[i.name]:i,[s.name]:s,[l.name]:l,...t.get()};return u.from(o(e)).fold((()=>(e=>{const t=y(e),n=t.indexOf("versions");return-1!==n&&(t.splice(n,1),t.push("versions")),{tabs:e,names:t}})(c)),(e=>((e,t)=>{const a={},o=p(e,(e=>{var o;if(r(e))return k(t,e)&&(a[e]=t[e]),e;{const t=null!==(o=e.name)&&void 0!==o?o:n("tab-name");return a[t]=e,t}}));return{tabs:a,names:o}})(e,c)))})(e,t),s={type:"tabpanel",tabs:(e=>{const t=[],n=e=>{t.push(e)};for(let t=0;t{return k(t=a,n=e)?u.from(t[n]):u.none();var t,n})))};e.windowManager.open({title:"Help",size:"medium",body:s,buttons:[{type:"cancel",name:"close",text:"Close",primary:!0}],initialData:{}})};e.add("help",(e=>{const t=(e=>{let t={};return{get:()=>t,set:e=>{t=e}}})(),a=(e=>({addTab:t=>{var a;const o=null!==(a=t.name)&&void 0!==a?a:n("tab-name"),i=e.get();i[o]=t,e.set(i)}}))(t);(e=>{(0,e.options.register)("help_tabs",{processor:"array"})})(e);const o=S(e,t);return((e,t)=>{e.ui.registry.addButton("help",{icon:"help",tooltip:"Help",onAction:t}),e.ui.registry.addMenuItem("help",{text:"Help",icon:"help",shortcut:"Alt+0",onAction:t})})(e,o),((e,t)=>{e.addCommand("mceHelp",t)})(e,o),e.shortcuts.add("Alt+0","Open help dialog","mceHelp"),a}))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/image/plugin.min.js b/public/plugins/tinymce/plugins/image/plugin.min.js new file mode 100644 index 000000000..982afc101 --- /dev/null +++ b/public/plugins/tinymce/plugins/image/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=Object.getPrototypeOf,a=(e,t,a)=>{var i;return!!a(e,t.prototype)||(null===(i=e.constructor)||void 0===i?void 0:i.name)===t.name},i=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&a(e,String,((e,t)=>t.isPrototypeOf(e)))?"string":t})(t)===e,s=e=>t=>typeof t===e,r=i("string"),o=i("object"),n=e=>((e,i)=>o(e)&&a(e,i,((e,a)=>t(e)===a)))(e,Object),l=i("array"),c=(null,e=>null===e);const m=s("boolean"),d=e=>!(e=>null==e)(e),g=s("function"),u=s("number"),p=()=>{};class h{constructor(e,t){this.tag=e,this.value=t}static some(e){return new h(!0,e)}static none(){return h.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?h.some(e(this.value)):h.none()}bind(e){return this.tag?e(this.value):h.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:h.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return d(e)?h.some(e):h.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}h.singletonNone=new h(!1);const b=Object.keys,v=Object.hasOwnProperty,y=(e,t)=>v.call(e,t),f=Array.prototype.push,w=e=>{const t=[];for(let a=0,i=e.length;a{((e,t,a)=>{if(!(r(a)||m(a)||u(a)))throw console.error("Invalid call to Attribute.set. Key ",t,":: Value ",a,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(t,a+"")})(e.dom,t,a)},D=e=>{if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}},_=D;var C=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),I=tinymce.util.Tools.resolve("tinymce.util.URI");const U=e=>e.length>0,x=e=>t=>t.options.get(e),S=x("image_dimensions"),N=x("image_advtab"),T=x("image_uploadtab"),O=x("image_prepend_url"),L=x("image_class_list"),E=x("image_description"),j=x("image_title"),M=x("image_caption"),R=x("image_list"),k=x("a11y_advanced_options"),z=x("automatic_uploads"),P=(e,t)=>Math.max(parseInt(e,10),parseInt(t,10)),B=e=>(e&&(e=e.replace(/px$/,"")),e),F=e=>(e.length>0&&/^[0-9]+$/.test(e)&&(e+="px"),e),H=e=>"IMG"===e.nodeName&&(e.hasAttribute("data-mce-object")||e.hasAttribute("data-mce-placeholder")),G=(e,t)=>{const a=e.options.get;return I.isDomSafe(t,"img",{allow_html_data_urls:a("allow_html_data_urls"),allow_script_urls:a("allow_script_urls"),allow_svg_data_urls:a("allow_svg_data_urls")})},W=C.DOM,$=e=>e.style.marginLeft&&e.style.marginRight&&e.style.marginLeft===e.style.marginRight?B(e.style.marginLeft):"",V=e=>e.style.marginTop&&e.style.marginBottom&&e.style.marginTop===e.style.marginBottom?B(e.style.marginTop):"",K=e=>e.style.borderWidth?B(e.style.borderWidth):"",Z=(e,t)=>{var a;return e.hasAttribute(t)&&null!==(a=e.getAttribute(t))&&void 0!==a?a:""},q=e=>null!==e.parentNode&&"FIGURE"===e.parentNode.nodeName,J=(e,t,a)=>{""===a||null===a?e.removeAttribute(t):e.setAttribute(t,a)},Q=(e,t)=>{const a=e.getAttribute("style"),i=t(null!==a?a:"");i.length>0?(e.setAttribute("style",i),e.setAttribute("data-mce-style",i)):e.removeAttribute("style")},X=(e,t)=>(e,a,i)=>{const s=e.style;s[a]?(s[a]=F(i),Q(e,t)):J(e,a,i)},Y=(e,t)=>e.style[t]?B(e.style[t]):Z(e,t),ee=(e,t)=>{const a=F(t);e.style.marginLeft=a,e.style.marginRight=a},te=(e,t)=>{const a=F(t);e.style.marginTop=a,e.style.marginBottom=a},ae=(e,t)=>{const a=F(t);e.style.borderWidth=a},ie=(e,t)=>{e.style.borderStyle=t},se=e=>{var t;return null!==(t=e.style.borderStyle)&&void 0!==t?t:""},re=e=>d(e)&&"FIGURE"===e.nodeName,oe=e=>0===W.getAttrib(e,"alt").length&&"presentation"===W.getAttrib(e,"role"),ne=e=>oe(e)?"":Z(e,"alt"),le=(e,t)=>{var a;const i=document.createElement("img");return J(i,"style",t.style),($(i)||""!==t.hspace)&&ee(i,t.hspace),(V(i)||""!==t.vspace)&&te(i,t.vspace),(K(i)||""!==t.border)&&ae(i,t.border),(se(i)||""!==t.borderStyle)&&ie(i,t.borderStyle),e(null!==(a=i.getAttribute("style"))&&void 0!==a?a:"")},ce=(e,t)=>({src:Z(t,"src"),alt:ne(t),title:Z(t,"title"),width:Y(t,"width"),height:Y(t,"height"),class:Z(t,"class"),style:e(Z(t,"style")),caption:q(t),hspace:$(t),vspace:V(t),border:K(t),borderStyle:se(t),isDecorative:oe(t)}),me=(e,t,a,i,s)=>{a[i]!==t[i]&&s(e,i,String(a[i]))},de=(e,t,a)=>{if(a){W.setAttrib(e,"role","presentation");const t=_(e);A(t,"alt","")}else{if(c(t)){"alt",_(e).dom.removeAttribute("alt")}else{const a=_(e);A(a,"alt",t)}"presentation"===W.getAttrib(e,"role")&&W.setAttrib(e,"role","")}},ge=(e,t)=>(a,i,s)=>{e(a,s),Q(a,t)},ue=(e,t,a)=>{const i=ce(e,a);me(a,i,t,"caption",((e,t,a)=>(e=>{q(e)?(e=>{const t=e.parentNode;d(t)&&(W.insertAfter(e,t),W.remove(t))})(e):(e=>{const t=W.create("figure",{class:"image"});W.insertAfter(t,e),t.appendChild(e),t.appendChild(W.create("figcaption",{contentEditable:"true"},"Caption")),t.contentEditable="false"})(e)})(e))),me(a,i,t,"src",J),me(a,i,t,"title",J),me(a,i,t,"width",X(0,e)),me(a,i,t,"height",X(0,e)),me(a,i,t,"class",J),me(a,i,t,"style",ge(((e,t)=>J(e,"style",t)),e)),me(a,i,t,"hspace",ge(ee,e)),me(a,i,t,"vspace",ge(te,e)),me(a,i,t,"border",ge(ae,e)),me(a,i,t,"borderStyle",ge(ie,e)),((e,t,a)=>{a.alt===t.alt&&a.isDecorative===t.isDecorative||de(e,a.alt,a.isDecorative)})(a,i,t)},pe=(e,t)=>{const a=(e=>{if(e.margin){const t=String(e.margin).split(" ");switch(t.length){case 1:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[0],e["margin-bottom"]=e["margin-bottom"]||t[0],e["margin-left"]=e["margin-left"]||t[0];break;case 2:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[1],e["margin-bottom"]=e["margin-bottom"]||t[0],e["margin-left"]=e["margin-left"]||t[1];break;case 3:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[1],e["margin-bottom"]=e["margin-bottom"]||t[2],e["margin-left"]=e["margin-left"]||t[1];break;case 4:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[1],e["margin-bottom"]=e["margin-bottom"]||t[2],e["margin-left"]=e["margin-left"]||t[3]}delete e.margin}return e})(e.dom.styles.parse(t)),i=e.dom.styles.parse(e.dom.styles.serialize(a));return e.dom.styles.serialize(i)},he=e=>{const t=e.selection.getNode(),a=e.dom.getParent(t,"figure.image");return a?e.dom.select("img",a)[0]:t&&("IMG"!==t.nodeName||H(t))?null:t},be=(e,t)=>{var a;const i=e.dom,s=((t,a)=>{const i={};var s;return((e,t,a,i)=>{((e,t)=>{const a=b(e);for(let i=0,s=a.length;i{(t(e,s)?a:i)(e,s)}))})(t,((t,a)=>!e.schema.isValidChild(a,"figure")),(s=i,(e,t)=>{s[t]=e}),p),i})(e.schema.getTextBlockElements()),r=i.getParent(t.parentNode,(e=>{return t=s,a=e.nodeName,y(t,a)&&void 0!==t[a]&&null!==t[a];var t,a}),e.getBody());return r&&null!==(a=i.split(r,t))&&void 0!==a?a:t},ve=(e,t)=>{const a=((t,a)=>{const i=document.createElement("img");if(ue((t=>pe(e,t)),{...a,caption:!1},i),de(i,a.alt,a.isDecorative),a.caption){const e=W.create("figure",{class:"image"});return e.appendChild(i),e.appendChild(W.create("figcaption",{contentEditable:"true"},"Caption")),e.contentEditable="false",e}return i})(0,t);e.dom.setAttrib(a,"data-mce-id","__mcenew"),e.focus(),e.selection.setContent(a.outerHTML);const i=e.dom.select('*[data-mce-id="__mcenew"]')[0];if(e.dom.setAttrib(i,"data-mce-id",null),re(i)){const t=be(e,i);e.selection.select(t)}else e.selection.select(i)},ye=(e,t)=>{const a=he(e);if(a){const i={...ce((t=>pe(e,t)),a),...t},s=((e,t)=>{const a=t.src;return{...t,src:G(e,a)?a:""}})(e,i);i.src?((e,t)=>{const a=he(e);if(a)if(ue((t=>pe(e,t)),t,a),((e,t)=>{e.dom.setAttrib(t,"src",t.getAttribute("src"))})(e,a),re(a.parentNode)){const t=a.parentNode;be(e,t),e.selection.select(a.parentNode)}else e.selection.select(a),((e,t,a)=>{const i=()=>{a.onload=a.onerror=null,e.selection&&(e.selection.select(a),e.nodeChanged())};a.onload=()=>{t.width||t.height||!S(e)||e.dom.setAttribs(a,{width:String(a.clientWidth),height:String(a.clientHeight)}),i()},a.onerror=i})(e,t,a)})(e,s):((e,t)=>{if(t){const a=e.dom.is(t.parentNode,"figure.image")?t.parentNode:t;e.dom.remove(a),e.focus(),e.nodeChanged(),e.dom.isEmpty(e.getBody())&&(e.setContent(""),e.selection.setCursorLocation())}})(e,a)}else t.src&&ve(e,{src:"",alt:"",title:"",width:"",height:"",class:"",style:"",caption:!1,hspace:"",vspace:"",border:"",borderStyle:"",isDecorative:!1,...t})},fe=(we=(e,t)=>n(e)&&n(t)?fe(e,t):t,(...e)=>{if(0===e.length)throw new Error("Can't merge zero objects");const t={};for(let a=0;ar(e.value)?e.value:"",Ce=(e,t)=>{const a=[];return De.each(e,(e=>{const i=(e=>r(e.text)?e.text:r(e.title)?e.title:"")(e);if(void 0!==e.menu){const s=Ce(e.menu,t);a.push({text:i,items:s})}else{const s=t(e);a.push({text:i,value:s})}})),a},Ie=(e=_e)=>t=>t?h.from(t).map((t=>Ce(t,e))):h.none(),Ue=(e,t)=>((e,a)=>{for(let a=0;ay(e,"items"))(i=e[a])?Ue(i.items,t):i.value===t?h.some(i):h.none();if(s.isSome())return s}var i;return h.none()})(e),xe=Ie,Se=(e,t)=>e.bind((e=>Ue(e,t))),Ne=e=>{const t=xe((t=>e.convertURL(t.value||t.url||"","src"))),a=new Promise((a=>{((e,t)=>{const a=R(e);r(a)?fetch(a).then((e=>{e.ok&&e.json().then(t)})):g(a)?a(t):t(a)})(e,(e=>{a(t(e).map((e=>w([[{text:"None",value:""}],e]))))}))})),i=(A=L(e),Ie(_e)(A)),s=N(e),o=T(e),n=(e=>U(e.options.get("images_upload_url")))(e),l=(e=>d(e.options.get("images_upload_handler")))(e),c=(e=>{const t=he(e);return t?ce((t=>pe(e,t)),t):{src:"",alt:"",title:"",width:"",height:"",class:"",style:"",caption:!1,hspace:"",vspace:"",border:"",borderStyle:"",isDecorative:!1}})(e),m=E(e),u=j(e),p=S(e),b=M(e),v=k(e),y=z(e),f=h.some(O(e)).filter((e=>r(e)&&e.length>0));var A;return a.then((e=>({image:c,imageList:e,classList:i,hasAdvTab:s,hasUploadTab:o,hasUploadUrl:n,hasUploadHandler:l,hasDescription:m,hasImageTitle:u,hasDimensions:p,hasImageCaption:b,prependURL:f,hasAccessibilityOptions:v,automaticUploads:y})))},Te=e=>{const t=e.imageList.map((e=>({name:"images",type:"listbox",label:"Image list",items:e}))),a={name:"alt",type:"input",label:"Alternative description",enabled:!(e.hasAccessibilityOptions&&e.image.isDecorative)},i=e.classList.map((e=>({name:"classes",type:"listbox",label:"Class",items:e})));return w([[{name:"src",type:"urlinput",filetype:"image",label:"Source"}],t.toArray(),e.hasAccessibilityOptions&&e.hasDescription?[{type:"label",label:"Accessibility",items:[{name:"isDecorative",type:"checkbox",label:"Image is decorative"}]}]:[],e.hasDescription?[a]:[],e.hasImageTitle?[{name:"title",type:"input",label:"Image title"}]:[],e.hasDimensions?[{name:"dimensions",type:"sizeinput"}]:[],[{...(s=e.classList.isSome()&&e.hasImageCaption,s?{type:"grid",columns:2}:{type:"panel"}),items:w([i.toArray(),e.hasImageCaption?[{type:"label",label:"Caption",items:[{type:"checkbox",name:"caption",label:"Show caption"}]}]:[]])}]]);var s},Oe=e=>({title:"General",name:"general",items:Te(e)}),Le=Te,Ee=e=>({src:{value:e.src,meta:{}},images:e.src,alt:e.alt,title:e.title,dimensions:{width:e.width,height:e.height},classes:e.class,caption:e.caption,style:e.style,vspace:e.vspace,border:e.border,hspace:e.hspace,borderstyle:e.borderStyle,fileinput:[],isDecorative:e.isDecorative}),je=(e,t)=>({src:e.src.value,alt:null!==e.alt&&0!==e.alt.length||!t?e.alt:null,title:e.title,width:e.dimensions.width,height:e.dimensions.height,class:e.classes,style:e.style,caption:e.caption,hspace:e.hspace,vspace:e.vspace,border:e.border,borderStyle:e.borderstyle,isDecorative:e.isDecorative}),Me=(e,t,a,i)=>{((e,t)=>{const a=t.getData();((e,t)=>/^(?:[a-zA-Z]+:)?\/\//.test(t)?h.none():e.prependURL.bind((e=>t.substring(0,e.length)!==e?h.some(e+t):h.none())))(e,a.src.value).each((e=>{t.setData({src:{value:e,meta:a.src.meta}})}))})(t,i),((e,t)=>{const a=t.getData(),i=a.src.meta;if(void 0!==i){const s=fe({},a);((e,t,a)=>{e.hasDescription&&r(a.alt)&&(t.alt=a.alt),e.hasAccessibilityOptions&&(t.isDecorative=a.isDecorative||t.isDecorative||!1),e.hasImageTitle&&r(a.title)&&(t.title=a.title),e.hasDimensions&&(r(a.width)&&(t.dimensions.width=a.width),r(a.height)&&(t.dimensions.height=a.height)),r(a.class)&&Se(e.classList,a.class).each((e=>{t.classes=e.value})),e.hasImageCaption&&m(a.caption)&&(t.caption=a.caption),e.hasAdvTab&&(r(a.style)&&(t.style=a.style),r(a.vspace)&&(t.vspace=a.vspace),r(a.border)&&(t.border=a.border),r(a.hspace)&&(t.hspace=a.hspace),r(a.borderstyle)&&(t.borderstyle=a.borderstyle))})(e,s,i),t.setData(s)}})(t,i),((e,t,a,i)=>{const s=i.getData(),r=s.src.value,o=s.src.meta||{};o.width||o.height||!t.hasDimensions||(U(r)?e.imageSize(r).then((e=>{a.open&&i.setData({dimensions:e})})).catch((e=>console.error(e))):i.setData({dimensions:{width:"",height:""}}))})(e,t,a,i),((e,t,a)=>{const i=a.getData(),s=Se(e.imageList,i.src.value);t.prevImage=s,a.setData({images:s.map((e=>e.value)).getOr("")})})(t,a,i)},Re=(e,t,a,i)=>{const s=i.getData();var r;i.block("Uploading image"),(r=s.fileinput,((e,t)=>0{i.unblock()}),(s=>{const r=URL.createObjectURL(s),o=()=>{i.unblock(),URL.revokeObjectURL(r)},n=s=>{i.setData({src:{value:s,meta:{}}}),i.showTab("general"),Me(e,t,a,i)};var l;(l=s,new Promise(((e,t)=>{const a=new FileReader;a.onload=()=>{e(a.result)},a.onerror=()=>{var e;t(null===(e=a.error)||void 0===e?void 0:e.message)},a.readAsDataURL(l)}))).then((a=>{const l=e.createBlobCache(s,r,a);t.automaticUploads?e.uploadImage(l).then((e=>{n(e.url),o()})).catch((t=>{o(),e.alertErr(t)})):(e.addToBlobCache(l),n(l.blobUri()),i.unblock())}))}))},ke=(e,t,a)=>(i,s)=>{"src"===s.name?Me(e,t,a,i):"images"===s.name?((e,t,a,i)=>{const s=i.getData(),r=Se(t.imageList,s.images);r.each((e=>{const t=""===s.alt||a.prevImage.map((e=>e.text===s.alt)).getOr(!1);t?""===e.value?i.setData({src:e,alt:a.prevAlt}):i.setData({src:e,alt:e.text}):i.setData({src:e})})),a.prevImage=r,Me(e,t,a,i)})(e,t,a,i):"alt"===s.name?a.prevAlt=i.getData().alt:"fileinput"===s.name?Re(e,t,a,i):"isDecorative"===s.name&&i.setEnabled("alt",!i.getData().isDecorative)},ze=e=>()=>{e.open=!1},Pe=e=>e.hasAdvTab||e.hasUploadUrl||e.hasUploadHandler?{type:"tabpanel",tabs:w([[Oe(e)],e.hasAdvTab?[{title:"Advanced",name:"advanced",items:[{type:"grid",columns:2,items:[{type:"input",label:"Vertical space",name:"vspace",inputMode:"numeric"},{type:"input",label:"Horizontal space",name:"hspace",inputMode:"numeric"},{type:"input",label:"Border width",name:"border",inputMode:"numeric"},{type:"listbox",name:"borderstyle",label:"Border style",items:[{text:"Select...",value:""},{text:"Solid",value:"solid"},{text:"Dotted",value:"dotted"},{text:"Dashed",value:"dashed"},{text:"Double",value:"double"},{text:"Groove",value:"groove"},{text:"Ridge",value:"ridge"},{text:"Inset",value:"inset"},{text:"Outset",value:"outset"},{text:"None",value:"none"},{text:"Hidden",value:"hidden"}]}]}]}]:[],e.hasUploadTab&&(e.hasUploadUrl||e.hasUploadHandler)?[{title:"Upload",name:"upload",items:[{type:"dropzone",name:"fileinput"}]}]:[]])}:{type:"panel",items:Le(e)},Be=(e,t,a)=>i=>{const s=fe(Ee(t.image),i.getData()),r={...s,style:le(a.normalizeCss,je(s,!1))};e.execCommand("mceUpdateImage",!1,je(r,t.hasAccessibilityOptions)),e.editorUpload.uploadImagesAuto(),i.close()},Fe=e=>t=>G(e,t)?(e=>new Promise((t=>{const a=document.createElement("img"),i=e=>{a.onload=a.onerror=null,a.parentNode&&a.parentNode.removeChild(a),t(e)};a.onload=()=>{const e={width:P(a.width,a.clientWidth),height:P(a.height,a.clientHeight)};i(Promise.resolve(e))},a.onerror=()=>{i(Promise.reject(`Failed to get image dimensions for: ${e}`))};const s=a.style;s.visibility="hidden",s.position="fixed",s.bottom=s.left="0px",s.width=s.height="auto",document.body.appendChild(a),a.src=e})))(e.documentBaseURI.toAbsolute(t)).then((e=>({width:String(e.width),height:String(e.height)}))):Promise.resolve({width:"",height:""}),He=e=>(t,a,i)=>{var s;return e.editorUpload.blobCache.create({blob:t,blobUri:a,name:null===(s=t.name)||void 0===s?void 0:s.replace(/\.[^\.]+$/,""),filename:t.name,base64:i.split(",")[1]})},Ge=e=>t=>{e.editorUpload.blobCache.add(t)},We=e=>t=>{e.windowManager.alert(t)},$e=e=>t=>pe(e,t),Ve=e=>t=>e.dom.parseStyle(t),Ke=e=>(t,a)=>e.dom.serializeStyle(t,a),Ze=e=>t=>Ae(e).upload([t],!1).then((e=>{var t;return 0===e.length?Promise.reject("Failed to upload image"):!1===e[0].status?Promise.reject(null===(t=e[0].error)||void 0===t?void 0:t.message):e[0]})),qe=e=>{const t={imageSize:Fe(e),addToBlobCache:Ge(e),createBlobCache:He(e),alertErr:We(e),normalizeCss:$e(e),parseStyle:Ve(e),serializeStyle:Ke(e),uploadImage:Ze(e)};return{open:()=>{Ne(e).then((a=>{const i=(e=>({prevImage:Se(e.imageList,e.image.src),prevAlt:e.image.alt,open:!0}))(a);return{title:"Insert/Edit Image",size:"normal",body:Pe(a),buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:Ee(a.image),onSubmit:Be(e,a,t),onChange:ke(t,a,i),onClose:ze(i)}})).then(e.windowManager.open)}}},Je=e=>{const t=e.attr("class");return d(t)&&/\bimage\b/.test(t)},Qe=e=>t=>{let a=t.length;const i=t=>{t.attr("contenteditable",e?"true":null)};for(;a--;){const s=t[a];Je(s)&&(s.attr("contenteditable",e?"false":null),De.each(s.getAll("figcaption"),i))}};e.add("image",(e=>{(e=>{const t=e.options.register;t("image_dimensions",{processor:"boolean",default:!0}),t("image_advtab",{processor:"boolean",default:!1}),t("image_uploadtab",{processor:"boolean",default:!0}),t("image_prepend_url",{processor:"string",default:""}),t("image_class_list",{processor:"object[]"}),t("image_description",{processor:"boolean",default:!0}),t("image_title",{processor:"boolean",default:!1}),t("image_caption",{processor:"boolean",default:!1}),t("image_list",{processor:e=>{const t=!1===e||r(e)||((e,t)=>{if(l(e)){for(let a=0,i=e.length;a{e.on("PreInit",(()=>{e.parser.addNodeFilter("figure",Qe(!0)),e.serializer.addNodeFilter("figure",Qe(!1))}))})(e),(e=>{e.ui.registry.addToggleButton("image",{icon:"image",tooltip:"Insert/edit image",onAction:qe(e).open,onSetup:t=>(t.setActive(d(he(e))),e.selection.selectorChangedWithUnbind("img:not([data-mce-object]):not([data-mce-placeholder]),figure.image",t.setActive).unbind)}),e.ui.registry.addMenuItem("image",{icon:"image",text:"Image...",onAction:qe(e).open}),e.ui.registry.addContextMenu("image",{update:e=>re(e)||"IMG"===e.nodeName&&!H(e)?["image"]:[]})})(e),(e=>{e.addCommand("mceImage",qe(e).open),e.addCommand("mceUpdateImage",((t,a)=>{e.undoManager.transact((()=>ye(e,a)))}))})(e)}))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/importcss/plugin.min.js b/public/plugins/tinymce/plugins/importcss/plugin.min.js new file mode 100644 index 000000000..5fe478571 --- /dev/null +++ b/public/plugins/tinymce/plugins/importcss/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(s=r=e,(o=String).prototype.isPrototypeOf(s)||(null===(n=r.constructor)||void 0===n?void 0:n.name)===o.name)?"string":t;var s,r,o,n})(t)===e,s=t("string"),r=t("object"),o=t("array"),n=("function",e=>"function"==typeof e);var c=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),i=tinymce.util.Tools.resolve("tinymce.EditorManager"),l=tinymce.util.Tools.resolve("tinymce.Env"),a=tinymce.util.Tools.resolve("tinymce.util.Tools");const p=e=>t=>t.options.get(e),u=p("importcss_merge_classes"),m=p("importcss_exclusive"),f=p("importcss_selector_converter"),y=p("importcss_selector_filter"),d=p("importcss_groups"),h=p("importcss_append"),_=p("importcss_file_filter"),g=p("skin"),v=p("skin_url"),b=Array.prototype.push,x=/^\.(?:ephox|tiny-pageembed|mce)(?:[.-]+\w+)+$/,T=e=>s(e)?t=>-1!==t.indexOf(e):e instanceof RegExp?t=>e.test(t):e,S=(e,t)=>{let s={};const r=/^(?:([a-z0-9\-_]+))?(\.[a-z0-9_\-\.]+)$/i.exec(t);if(!r)return;const o=r[1],n=r[2].substr(1).split(".").join(" "),c=a.makeMap("a,img");return r[1]?(s={title:t},e.schema.getTextBlockElements()[o]?s.block=o:e.schema.getBlockElements()[o]||c[o.toLowerCase()]?s.selector=o:s.inline=o):r[2]&&(s={inline:"span",title:t.substr(1),classes:n}),u(e)?s.classes=n:s.attributes={class:n},s},k=(e,t)=>null===t||m(e),w=e=>{e.on("init",(()=>{const t=(()=>{const e=[],t=[],s={};return{addItemToGroup:(e,r)=>{s[e]?s[e].push(r):(t.push(e),s[e]=[r])},addItem:t=>{e.push(t)},toFormats:()=>{return(r=t,n=e=>{const t=s[e];return 0===t.length?[]:[{title:e,items:t}]},(e=>{const t=[];for(let s=0,r=e.length;s{const s=e.length,r=new Array(s);for(let o=0;oa.map(e,(e=>a.extend({},e,{original:e,selectors:{},filter:T(e.filter)}))))(d(e)),u=(t,s)=>{if(((e,t,s,r)=>!(k(e,s)?t in r:t in s.selectors))(e,t,s,r)){((e,t,s,r)=>{k(e,s)?r[t]=!0:s.selectors[t]=!0})(e,t,s,r);const o=((e,t,s,r)=>{let o;const n=f(e);return o=r&&r.selector_converter?r.selector_converter:n||(()=>S(e,s)),o.call(t,s,r)})(e,e.plugins.importcss,t,s);if(o){const t=o.name||c.DOM.uniqueId();return e.formatter.register(t,o),{title:o.title,format:t}}}return null};a.each(((e,t,r)=>{const o=[],n={},c=(t,n)=>{let p,u=t.href;if(u=(e=>{const t=l.cacheSuffix;return s(e)&&(e=e.replace("?"+t,"").replace("&"+t,"")),e})(u),u&&(!r||r(u,n))&&!((e,t)=>{const s=g(e);if(s){const r=v(e),o=r?e.documentBaseURI.toAbsolute(r):i.baseURL+"/skins/ui/"+s,n=i.baseURL+"/skins/content/";return t===o+"/content"+(e.inline?".inline":"")+".min.css"||-1!==t.indexOf(n)}return!1})(e,u)){a.each(t.imports,(e=>{c(e,!0)}));try{p=t.cssRules||t.rules}catch(e){}a.each(p,(e=>{e.styleSheet?c(e.styleSheet,!0):e.selectorText&&a.each(e.selectorText.split(","),(e=>{o.push(a.trim(e))}))}))}};a.each(e.contentCSS,(e=>{n[e]=!0})),r||(r=(e,t)=>t||n[e]);try{a.each(t.styleSheets,(e=>{c(e)}))}catch(e){}return o})(e,e.getDoc(),T(_(e))),(e=>{if(!x.test(e)&&(!n||n(e))){const s=((e,t)=>a.grep(e,(e=>!e.filter||e.filter(t))))(p,e);if(s.length>0)a.each(s,(s=>{const r=u(e,s);r&&t.addItemToGroup(s.title,r)}));else{const s=u(e,null);s&&t.addItem(s)}}}));const m=t.toFormats();e.dispatch("addStyleModifications",{items:m,replace:!h(e)})}))};e.add("importcss",(e=>((e=>{const t=e.options.register,o=e=>s(e)||n(e)||r(e);t("importcss_merge_classes",{processor:"boolean",default:!0}),t("importcss_exclusive",{processor:"boolean",default:!0}),t("importcss_selector_converter",{processor:"function"}),t("importcss_selector_filter",{processor:o}),t("importcss_file_filter",{processor:o}),t("importcss_groups",{processor:"object[]"}),t("importcss_append",{processor:"boolean",default:!1})})(e),w(e),(e=>({convertSelectorToFormat:t=>S(e,t)}))(e))))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/insertdatetime/plugin.min.js b/public/plugins/tinymce/plugins/insertdatetime/plugin.min.js new file mode 100644 index 000000000..db7958d56 --- /dev/null +++ b/public/plugins/tinymce/plugins/insertdatetime/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>t.options.get(e),a=t("insertdatetime_dateformat"),r=t("insertdatetime_timeformat"),n=t("insertdatetime_formats"),s=t("insertdatetime_element"),i="Sun Mon Tue Wed Thu Fri Sat Sun".split(" "),o="Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(" "),l="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),m="January February March April May June July August September October November December".split(" "),c=(e,t)=>{if((e=""+e).length(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=t.replace("%D","%m/%d/%Y")).replace("%r","%I:%M:%S %p")).replace("%Y",""+a.getFullYear())).replace("%y",""+a.getYear())).replace("%m",c(a.getMonth()+1,2))).replace("%d",c(a.getDate(),2))).replace("%H",""+c(a.getHours(),2))).replace("%M",""+c(a.getMinutes(),2))).replace("%S",""+c(a.getSeconds(),2))).replace("%I",""+((a.getHours()+11)%12+1))).replace("%p",a.getHours()<12?"AM":"PM")).replace("%B",""+e.translate(m[a.getMonth()]))).replace("%b",""+e.translate(l[a.getMonth()]))).replace("%A",""+e.translate(o[a.getDay()]))).replace("%a",""+e.translate(i[a.getDay()]))).replace("%%","%"),u=(e,t)=>{if(s(e)){const a=d(e,t);let r;r=/%[HMSIp]/.test(t)?d(e,"%Y-%m-%dT%H:%M"):d(e,"%Y-%m-%d");const n=e.dom.getParent(e.selection.getStart(),"time");n?((e,t,a,r)=>{const n=e.dom.create("time",{datetime:a},r);e.dom.replace(n,t),e.selection.select(n,!0),e.selection.collapse(!1)})(e,n,r,a):e.insertContent('")}else e.insertContent(d(e,t))};var p=tinymce.util.Tools.resolve("tinymce.util.Tools");e.add("insertdatetime",(e=>{(e=>{const t=e.options.register;t("insertdatetime_dateformat",{processor:"string",default:e.translate("%Y-%m-%d")}),t("insertdatetime_timeformat",{processor:"string",default:e.translate("%H:%M:%S")}),t("insertdatetime_formats",{processor:"string[]",default:["%H:%M:%S","%Y-%m-%d","%I:%M:%S %p","%D"]}),t("insertdatetime_element",{processor:"boolean",default:!1})})(e),(e=>{e.addCommand("mceInsertDate",((t,r)=>{u(e,null!=r?r:a(e))})),e.addCommand("mceInsertTime",((t,a)=>{u(e,null!=a?a:r(e))}))})(e),(e=>{const t=n(e),a=(e=>{let t=e;return{get:()=>t,set:e=>{t=e}}})((e=>{const t=n(e);return t.length>0?t[0]:r(e)})(e)),s=t=>e.execCommand("mceInsertDate",!1,t);e.ui.registry.addSplitButton("insertdatetime",{icon:"insert-time",tooltip:"Insert date/time",select:e=>e===a.get(),fetch:a=>{a(p.map(t,(t=>({type:"choiceitem",text:d(e,t),value:t}))))},onAction:e=>{s(a.get())},onItemAction:(e,t)=>{a.set(t),s(t)}});const i=e=>()=>{a.set(e),s(e)};e.ui.registry.addNestedMenuItem("insertdatetime",{icon:"insert-time",text:"Date/time",getSubmenuItems:()=>p.map(t,(t=>({type:"menuitem",text:d(e,t),onAction:i(t)})))})})(e)}))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/link/plugin.min.js b/public/plugins/tinymce/plugins/link/plugin.min.js new file mode 100644 index 000000000..3658953e6 --- /dev/null +++ b/public/plugins/tinymce/plugins/link/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=o=e,(r=String).prototype.isPrototypeOf(n)||(null===(l=o.constructor)||void 0===l?void 0:l.name)===r.name)?"string":t;var n,o,r,l})(t)===e,n=e=>t=>typeof t===e,o=t("string"),r=t("object"),l=t("array"),a=(null,e=>null===e);const i=n("boolean"),s=e=>!(e=>null==e)(e),c=n("function"),u=(e,t)=>{if(l(e)){for(let n=0,o=e.length;n{},d=(e,t)=>e===t;class m{constructor(e,t){this.tag=e,this.value=t}static some(e){return new m(!0,e)}static none(){return m.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?m.some(e(this.value)):m.none()}bind(e){return this.tag?e(this.value):m.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:m.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return s(e)?m.some(e):m.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}m.singletonNone=new m(!1);const h=Array.prototype.indexOf,f=Array.prototype.push,p=e=>{const t=[];for(let n=0,o=e.length;n{for(let n=0;ne.exists((e=>n(e,t))),y=e=>{const t=[],n=e=>{t.push(e)};for(let t=0;te?m.some(t):m.none(),b=e=>t=>t.options.get(e),_=b("link_assume_external_targets"),w=b("link_context_toolbar"),C=b("link_list"),O=b("link_default_target"),N=b("link_default_protocol"),A=b("link_target_list"),S=b("link_rel_list"),T=b("link_class_list"),E=b("link_title"),P=b("allow_unsafe_link_target"),R=b("link_quicklink");var L=tinymce.util.Tools.resolve("tinymce.util.Tools");const M=e=>o(e.value)?e.value:"",D=(e,t)=>{const n=[];return L.each(e,(e=>{const r=(e=>o(e.text)?e.text:o(e.title)?e.title:"")(e);if(void 0!==e.menu){const o=D(e.menu,t);n.push({text:r,items:o})}else{const o=t(e);n.push({text:r,value:o})}})),n},B=(e=M)=>t=>m.from(t).map((t=>D(t,e))),I=e=>B(M)(e),j=B,K=(e,t)=>n=>({name:e,type:"listbox",label:t,items:n}),U=M,q=Object.keys,F=Object.hasOwnProperty,V=(e,t)=>F.call(e,t);var $=tinymce.util.Tools.resolve("tinymce.dom.TreeWalker"),z=tinymce.util.Tools.resolve("tinymce.util.URI");const G=e=>s(e)&&"a"===e.nodeName.toLowerCase(),H=e=>G(e)&&!!Q(e),J=(e,t)=>{if(e.collapsed)return[];{const n=e.cloneContents(),o=n.firstChild,r=new $(o,n),l=[];let a=o;do{t(a)&&l.push(a)}while(a=r.next());return l}},W=e=>/^\w+:/i.test(e),Q=e=>{var t,n;return null!==(n=null!==(t=e.getAttribute("data-mce-href"))&&void 0!==t?t:e.getAttribute("href"))&&void 0!==n?n:""},X=(e,t)=>{const n=["noopener"],o=e?e.split(/\s+/):[],r=e=>e.filter((e=>-1===L.inArray(n,e))),l=t?(e=>(e=r(e)).length>0?e.concat(n):n)(o):r(o);return l.length>0?(e=>L.trim(e.sort().join(" ")))(l):""},Y=(e,t)=>(t=t||e.selection.getNode(),oe(t)?m.from(e.dom.select("a[href]",t)[0]):m.from(e.dom.getParent(t,"a[href]"))),Z=(e,t)=>Y(e,t).isSome(),ee=(e,t)=>t.fold((()=>e.getContent({format:"text"})),(e=>e.innerText||e.textContent||"")).replace(/\uFEFF/g,""),te=e=>L.grep(e,H).length>0,ne=e=>{const t=e.schema.getTextInlineElements();if(Y(e).exists((e=>e.hasAttribute("data-mce-block"))))return!1;const n=e.selection.getRng();return!!n.collapsed||0===J(n,(e=>1===e.nodeType&&!G(e)&&!V(t,e.nodeName.toLowerCase()))).length},oe=e=>s(e)&&"FIGURE"===e.nodeName&&/\bimage\b/i.test(e.className),re=(e,t,n)=>{const o=e.selection.getNode(),r=Y(e,o),l=((e,t)=>{const n={...t};if(0===S(e).length&&!P(e)){const e=X(n.rel,"_blank"===n.target);n.rel=e||null}return m.from(n.target).isNone()&&!1===A(e)&&(n.target=O(e)),n.href=((e,t)=>"http"!==t&&"https"!==t||W(e)?e:t+"://"+e)(n.href,_(e)),n})(e,(e=>{return t=["title","rel","class","target"],n=(t,n)=>(e[n].each((e=>{t[n]=e.length>0?e:null})),t),o={href:e.href},((e,t)=>{for(let n=0,o=e.length;n{o=n(o,e)})),o;var t,n,o})(n));e.undoManager.transact((()=>{n.href===t.href&&t.attach(),r.fold((()=>{((e,t,n,o)=>{const r=e.dom;oe(t)?ce(r,t,o):n.fold((()=>{e.execCommand("mceInsertLink",!1,o)}),(t=>{e.insertContent(r.createHTML("a",o,r.encode(t)))}))})(e,o,n.text,l)}),(t=>{e.focus(),((e,t,n,o)=>{n.each((e=>{V(t,"innerText")?t.innerText=e:t.textContent=e})),e.dom.setAttribs(t,o),e.selection.select(t)})(e,t,n.text,l)}))}))},le=e=>{const{class:t,href:n,rel:o,target:r,text:l,title:i}=e;return((e,t)=>{const n={};var o;return((e,t,n,o)=>{((e,t)=>{const n=q(e);for(let o=0,r=n.length;o{(t(e,r)?n:o)(e,r)}))})(e,((e,t)=>!1===a(e)),(o=n,(e,t)=>{o[t]=e}),g),n})({class:t.getOrNull(),href:n,rel:o.getOrNull(),target:r.getOrNull(),text:l.getOrNull(),title:i.getOrNull()})},ae=(e,t,n)=>{const o=((e,t)=>{const n=e.options.get,o={allow_html_data_urls:n("allow_html_data_urls"),allow_script_urls:n("allow_script_urls"),allow_svg_data_urls:n("allow_svg_data_urls")},r=t.href;return{...t,href:z.isDomSafe(r,"a",o)?r:""}})(e,n);e.hasPlugin("rtc",!0)?e.execCommand("createlink",!1,le(o)):re(e,t,o)},ie=e=>{e.hasPlugin("rtc",!0)?e.execCommand("unlink"):(e=>{e.undoManager.transact((()=>{const t=e.selection.getNode();oe(t)?se(e,t):(e=>{const t=e.dom,n=e.selection,o=n.getBookmark(),r=n.getRng().cloneRange(),l=t.getParent(r.startContainer,"a[href]",e.getBody()),a=t.getParent(r.endContainer,"a[href]",e.getBody());l&&r.setStartBefore(l),a&&r.setEndAfter(a),n.setRng(r),e.execCommand("unlink"),n.moveToBookmark(o)})(e),e.focus()}))})(e)},se=(e,t)=>{var n;const o=e.dom.select("img",t)[0];if(o){const r=e.dom.getParents(o,"a[href]",t)[0];r&&(null===(n=r.parentNode)||void 0===n||n.insertBefore(o,r),e.dom.remove(r))}},ce=(e,t,n)=>{var o;const r=e.select("img",t)[0];if(r){const t=e.create("a",n);null===(o=r.parentNode)||void 0===o||o.insertBefore(t,r),t.appendChild(r)}},ue=(e,t)=>k(t,(t=>(e=>{return V(t=e,n="items")&&void 0!==t[n]&&null!==t[n];var t,n})(t)?ue(e,t.items):x(t.value===e,t))),ge=(e,t)=>{const n={text:e.text,title:e.title},o=(e,o)=>{const r=(l=t,a=o,"link"===a?l.link:"anchor"===a?l.anchor:m.none()).getOr([]);var l,a;return((e,t,n,o)=>{const r=o[t],l=e.length>0;return void 0!==r?ue(r,n).map((t=>({url:{value:t.value,meta:{text:l?e:t.text,attach:g}},text:l?e:t.text}))):m.none()})(n.text,o,r,e)};return{onChange:(e,t)=>{const r=t.name;return"url"===r?(e=>{const t=(o=e.url,x(n.text.length<=0,m.from(null===(r=o.meta)||void 0===r?void 0:r.text).getOr(o.value)));var o,r;const l=(e=>{var t;return x(n.title.length<=0,m.from(null===(t=e.meta)||void 0===t?void 0:t.title).getOr(""))})(e.url);return t.isSome()||l.isSome()?m.some({...t.map((e=>({text:e}))).getOr({}),...l.map((e=>({title:e}))).getOr({})}):m.none()})(e()):((e,t)=>h.call(e,t))(["anchor","link"],r)>-1?o(e(),r):"text"===r||"title"===r?(n[r]=e()[r],m.none()):m.none()}}};var de=tinymce.util.Tools.resolve("tinymce.util.Delay");const me=e=>{const t=e.href;return t.indexOf("@")>0&&-1===t.indexOf("/")&&-1===t.indexOf("mailto:")?m.some({message:"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?",preprocess:e=>({...e,href:"mailto:"+t})}):m.none()},he=(e,t)=>n=>{const o=n.href;return 1===e&&!W(o)||0===e&&/^\s*www(\.|\d\.)/i.test(o)?m.some({message:`The URL you entered seems to be an external link. Do you want to add the required ${t}:// prefix?`,preprocess:e=>({...e,href:t+"://"+o})}):m.none()},fe=e=>{const t=e.dom.select("a:not([href])"),n=p(((e,t)=>{const n=e.length,o=new Array(n);for(let r=0;r{const t=e.name||e.id;return t?[{text:t,value:"#"+t}]:[]})));return n.length>0?m.some([{text:"None",value:""}].concat(n)):m.none()},pe=e=>{const t=T(e);return t.length>0?I(t):m.none()},ke=e=>{try{return m.some(JSON.parse(e))}catch(e){return m.none()}},ve=(e,t)=>{const n=S(e);if(n.length>0){const o=v(t,"_blank"),r=e=>X(U(e),o);return(!1===P(e)?j(r):I)(n)}return m.none()},ye=[{text:"Current window",value:""},{text:"New window",value:"_blank"}],xe=e=>{const t=A(e);return l(t)?I(t).orThunk((()=>m.some(ye))):!1===t?m.none():m.some(ye)},be=(e,t,n)=>{const o=e.getAttrib(t,n);return null!==o&&o.length>0?m.some(o):m.none()},_e=(e,t)=>(e=>{const t=t=>e.convertURL(t.value||t.url||"","href"),n=C(e);return new Promise((e=>{o(n)?fetch(n).then((e=>e.ok?e.text().then(ke):Promise.reject())).then(e,(()=>e(m.none()))):c(n)?n((t=>e(m.some(t)))):e(m.from(n))})).then((e=>e.bind(j(t)).map((e=>e.length>0?[{text:"None",value:""}].concat(e):e))))})(e).then((n=>{const o=((e,t)=>{const n=e.dom,o=ne(e)?m.some(ee(e.selection,t)):m.none(),r=t.bind((e=>m.from(n.getAttrib(e,"href")))),l=t.bind((e=>m.from(n.getAttrib(e,"target")))),a=t.bind((e=>be(n,e,"rel"))),i=t.bind((e=>be(n,e,"class")));return{url:r,text:o,title:t.bind((e=>be(n,e,"title"))),target:l,rel:a,linkClass:i}})(e,t);return{anchor:o,catalogs:{targets:xe(e),rels:ve(e,o.target),classes:pe(e),anchor:fe(e),link:n},optNode:t,flags:{titleEnabled:E(e)}}})),we=e=>{const t=(e=>{const t=Y(e);return _e(e,t)})(e);t.then((t=>{const n=((e,t)=>n=>{const o=n.getData();if(!o.url.value)return ie(e),void n.close();const r=e=>m.from(o[e]).filter((n=>!v(t.anchor[e],n))),l={href:o.url.value,text:r("text"),target:r("target"),rel:r("rel"),class:r("linkClass"),title:r("title")},a={href:o.url.value,attach:void 0!==o.url.meta&&o.url.meta.attach?o.url.meta.attach:g};((e,t)=>k([me,he(_(e),N(e))],(e=>e(t))).fold((()=>Promise.resolve(t)),(n=>new Promise((o=>{((e,t,n)=>{const o=e.selection.getRng();de.setEditorTimeout(e,(()=>{e.windowManager.confirm(t,(t=>{e.selection.setRng(o),n(t)}))}))})(e,n.message,(e=>{o(e?n.preprocess(t):t)}))})))))(e,l).then((t=>{ae(e,a,t)})),n.close()})(e,t);return((e,t,n)=>{const o=e.anchor.text.map((()=>({name:"text",type:"input",label:"Text to display"}))).toArray(),r=e.flags.titleEnabled?[{name:"title",type:"input",label:"Title"}]:[],l=((e,t)=>{const n=e.anchor,o=n.url.getOr("");return{url:{value:o,meta:{original:{value:o}}},text:n.text.getOr(""),title:n.title.getOr(""),anchor:o,link:o,rel:n.rel.getOr(""),target:n.target.or(t).getOr(""),linkClass:n.linkClass.getOr("")}})(e,m.from(O(n))),a=e.catalogs,i=ge(l,a);return{title:"Insert/Edit Link",size:"normal",body:{type:"panel",items:p([[{name:"url",type:"urlinput",filetype:"file",label:"URL"}],o,r,y([a.anchor.map(K("anchor","Anchors")),a.rels.map(K("rel","Rel")),a.targets.map(K("target","Open link in...")),a.link.map(K("link","Link list")),a.classes.map(K("linkClass","Class"))])])},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:l,onChange:(e,{name:t})=>{i.onChange(e.getData,{name:t}).each((t=>{e.setData(t)}))},onSubmit:t}})(t,n,e)})).then((t=>{e.windowManager.open(t)}))};var Ce=tinymce.util.Tools.resolve("tinymce.util.VK");const Oe=(e,t)=>e.dom.getParent(t,"a[href]"),Ne=e=>Oe(e,e.selection.getStart()),Ae=(e,t)=>{if(t){const n=Q(t);if(/^#/.test(n)){const t=e.dom.select(n);t.length&&e.selection.scrollIntoView(t[0],!0)}else(e=>{const t=document.createElement("a");t.target="_blank",t.href=e,t.rel="noreferrer noopener";const n=document.createEvent("MouseEvents");n.initMouseEvent("click",!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null),((e,t)=>{document.body.appendChild(e),e.dispatchEvent(t),document.body.removeChild(e)})(t,n)})(t.href)}},Se=e=>()=>{e.execCommand("mceLink",!1,{dialog:!0})},Te=e=>()=>{Ae(e,Ne(e))},Ee=(e,t)=>(e.on("NodeChange",t),()=>e.off("NodeChange",t)),Pe=e=>t=>{const n=()=>t.setActive(!e.mode.isReadOnly()&&Z(e,e.selection.getNode()));return n(),Ee(e,n)},Re=e=>t=>{const n=()=>t.setEnabled(Z(e,e.selection.getNode()));return n(),Ee(e,n)},Le=e=>t=>{const n=t=>{return te(t)||(n=e.selection.getRng(),J(n,H).length>0);var n},o=e.dom.getParents(e.selection.getStart());return t.setEnabled(n(o)),Ee(e,(e=>t.setEnabled(n(e.parents))))};e.add("link",(e=>{(e=>{const t=e.options.register;t("link_assume_external_targets",{processor:e=>{const t=o(e)||i(e);return t?!0===e?{value:1,valid:t}:"http"===e||"https"===e?{value:e,valid:t}:{value:0,valid:t}:{valid:!1,message:"Must be a string or a boolean."}},default:!1}),t("link_context_toolbar",{processor:"boolean",default:!1}),t("link_list",{processor:e=>o(e)||c(e)||u(e,r)}),t("link_default_target",{processor:"string"}),t("link_default_protocol",{processor:"string",default:"https"}),t("link_target_list",{processor:e=>i(e)||u(e,r),default:!0}),t("link_rel_list",{processor:"object[]",default:[]}),t("link_class_list",{processor:"object[]",default:[]}),t("link_title",{processor:"boolean",default:!0}),t("allow_unsafe_link_target",{processor:"boolean",default:!1}),t("link_quicklink",{processor:"boolean",default:!1})})(e),(e=>{e.ui.registry.addToggleButton("link",{icon:"link",tooltip:"Insert/edit link",onAction:Se(e),onSetup:Pe(e)}),e.ui.registry.addButton("openlink",{icon:"new-tab",tooltip:"Open link",onAction:Te(e),onSetup:Re(e)}),e.ui.registry.addButton("unlink",{icon:"unlink",tooltip:"Remove link",onAction:()=>ie(e),onSetup:Le(e)})})(e),(e=>{e.ui.registry.addMenuItem("openlink",{text:"Open link",icon:"new-tab",onAction:Te(e),onSetup:Re(e)}),e.ui.registry.addMenuItem("link",{icon:"link",text:"Link...",shortcut:"Meta+K",onAction:Se(e)}),e.ui.registry.addMenuItem("unlink",{icon:"unlink",text:"Remove link",onAction:()=>ie(e),onSetup:Le(e)})})(e),(e=>{e.ui.registry.addContextMenu("link",{update:t=>te(e.dom.getParents(t,"a"))?"link unlink openlink":"link"})})(e),(e=>{const t=t=>{const n=e.selection.getNode();return t.setEnabled(Z(e,n)),g};e.ui.registry.addContextForm("quicklink",{launch:{type:"contextformtogglebutton",icon:"link",tooltip:"Link",onSetup:Pe(e)},label:"Link",predicate:t=>w(e)&&Z(e,t),initValue:()=>Y(e).fold((()=>""),Q),commands:[{type:"contextformtogglebutton",icon:"link",tooltip:"Link",primary:!0,onSetup:t=>{const n=e.selection.getNode();return t.setActive(Z(e,n)),Pe(e)(t)},onAction:t=>{const n=t.getValue(),o=(t=>{const n=Y(e),o=ne(e);if(n.isNone()&&o){const o=ee(e.selection,n);return m.some(o.length>0?o:t)}return m.none()})(n);ae(e,{href:n,attach:g},{href:n,text:o,title:m.none(),rel:m.none(),target:m.none(),class:m.none()}),(e=>{e.selection.collapse(!1)})(e),t.hide()}},{type:"contextformbutton",icon:"unlink",tooltip:"Remove link",onSetup:t,onAction:t=>{ie(e),t.hide()}},{type:"contextformbutton",icon:"new-tab",tooltip:"Open link",onSetup:t,onAction:t=>{Te(e)(),t.hide()}}]})})(e),(e=>{e.on("click",(t=>{const n=Oe(e,t.target);n&&Ce.metaKeyPressed(t)&&(t.preventDefault(),Ae(e,n))})),e.on("keydown",(t=>{if(!t.isDefaultPrevented()&&13===t.keyCode&&(e=>!0===e.altKey&&!1===e.shiftKey&&!1===e.ctrlKey&&!1===e.metaKey)(t)){const n=Ne(e);n&&(t.preventDefault(),Ae(e,n))}}))})(e),(e=>{e.addCommand("mceLink",((t,n)=>{!0!==(null==n?void 0:n.dialog)&&R(e)?e.dispatch("contexttoolbar-show",{toolbarKey:"quicklink"}):we(e)}))})(e),(e=>{e.addShortcut("Meta+K","",(()=>{e.execCommand("mceLink")}))})(e)}))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/lists/plugin.min.js b/public/plugins/tinymce/plugins/lists/plugin.min.js new file mode 100644 index 000000000..b63900e5d --- /dev/null +++ b/public/plugins/tinymce/plugins/lists/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=t=>e=>(t=>{const e=typeof t;return null===t?"null":"object"===e&&Array.isArray(t)?"array":"object"===e&&(n=r=t,(o=String).prototype.isPrototypeOf(n)||(null===(s=r.constructor)||void 0===s?void 0:s.name)===o.name)?"string":e;var n,r,o,s})(e)===t,n=t=>e=>typeof e===t,r=e("string"),o=e("object"),s=e("array"),i=n("boolean"),a=t=>!(t=>null==t)(t),l=n("function"),d=n("number"),c=()=>{},u=(t,e)=>t===e,m=t=>e=>!t(e),p=(!1,()=>false);class g{constructor(t,e){this.tag=t,this.value=e}static some(t){return new g(!0,t)}static none(){return g.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?g.some(t(this.value)):g.none()}bind(t){return this.tag?t(this.value):g.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:g.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return a(t)?g.some(t):g.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}g.singletonNone=new g(!1);const h=Array.prototype.slice,f=Array.prototype.indexOf,y=Array.prototype.push,v=(t,e)=>{return n=t,r=e,f.call(n,r)>-1;var n,r},C=(t,e)=>{for(let n=0,r=t.length;n{const n=t.length,r=new Array(n);for(let o=0;o{for(let n=0,r=t.length;n{const n=[];for(let r=0,o=t.length;r(S(t,((t,r)=>{n=e(n,t,r)})),n),O=(t,e,n)=>{for(let r=0,o=t.length;rO(t,e,p),T=(t,e)=>(t=>{const e=[];for(let n=0,r=t.length;n{const e=h.call(t,0);return e.reverse(),e},w=(t,e)=>e>=0&&ew(t,0),E=t=>w(t,t.length-1),B=(t,e)=>{const n=[],r=l(e)?t=>C(n,(n=>e(n,t))):t=>v(n,t);for(let e=0,o=t.length;et.exists((t=>n(t,e))),I=(t,e,n)=>t.isSome()&&e.isSome()?g.some(n(t.getOrDie(),e.getOrDie())):g.none(),P=t=>{if(null==t)throw new Error("Node cannot be null or undefined");return{dom:t}},M=(t,e)=>{const n=(e||document).createElement(t);return P(n)},R=P,U=(t,e)=>t.dom===e.dom;"undefined"!=typeof window?window:Function("return this;")();const $=t=>t.dom.nodeName.toLowerCase(),_=(1,t=>1===(t=>t.dom.nodeType)(t));const H=t=>e=>_(e)&&$(e)===t,j=t=>g.from(t.dom.parentNode).map(R),F=t=>b(t.dom.childNodes,R),K=(t,e)=>{const n=t.dom.childNodes;return g.from(n[e]).map(R)},V=t=>K(t,0),z=t=>K(t,t.dom.childNodes.length-1),Q=(t,e,n)=>{let r=t.dom;const o=l(n)?n:p;for(;r.parentNode;){r=r.parentNode;const t=R(r);if(e(t))return g.some(t);if(o(t))break}return g.none()},q=(t,e,n)=>((t,e,n,r,o)=>r(n)?g.some(n):l(o)&&o(n)?g.none():e(n,r,o))(0,Q,t,e,n),W=(t,e)=>{j(t).each((n=>{n.dom.insertBefore(e.dom,t.dom)}))},Z=(t,e)=>{t.dom.appendChild(e.dom)},G=(t,e)=>{S(e,(e=>{Z(t,e)}))},J=t=>{t.dom.textContent="",S(F(t),(t=>{X(t)}))},X=t=>{const e=t.dom;null!==e.parentNode&&e.parentNode.removeChild(e)};var Y=tinymce.util.Tools.resolve("tinymce.dom.RangeUtils"),tt=tinymce.util.Tools.resolve("tinymce.dom.TreeWalker"),et=tinymce.util.Tools.resolve("tinymce.util.VK");const nt=t=>b(t,R),rt=Object.keys,ot=(t,e)=>{const n=rt(t);for(let r=0,o=n.length;r{const n=t.dom;ot(e,((t,e)=>{((t,e,n)=>{if(!(r(n)||i(n)||d(n)))throw console.error("Invalid call to Attribute.set. Key ",e,":: Value ",n,":: Element ",t),new Error("Attribute value was not simple");t.setAttribute(e,n+"")})(n,e,t)}))},it=t=>L(t.dom.attributes,((t,e)=>(t[e.name]=e.value,t)),{}),at=t=>((t,e)=>R(t.dom.cloneNode(!0)))(t),lt=(t,e)=>{const n=((t,e)=>{const n=M(e),r=it(t);return st(n,r),n})(t,e);((t,e)=>{const n=(t=>g.from(t.dom.nextSibling).map(R))(t);n.fold((()=>{j(t).each((t=>{Z(t,e)}))}),(t=>{W(t,e)}))})(t,n);const r=F(t);return G(n,r),X(t),n};var dt=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),ct=tinymce.util.Tools.resolve("tinymce.util.Tools");const ut=t=>e=>a(e)&&e.nodeName.toLowerCase()===t,mt=t=>e=>a(e)&&t.test(e.nodeName),pt=t=>a(t)&&3===t.nodeType,gt=t=>a(t)&&1===t.nodeType,ht=mt(/^(OL|UL|DL)$/),ft=mt(/^(OL|UL)$/),yt=ut("ol"),vt=mt(/^(LI|DT|DD)$/),Ct=mt(/^(DT|DD)$/),bt=mt(/^(TH|TD)$/),St=ut("br"),Nt=(t,e)=>a(e)&&e.nodeName in t.schema.getTextBlockElements(),Lt=(t,e)=>a(t)&&t.nodeName in e,Ot=(t,e,n)=>{const r=t.isEmpty(e);return!(n&&t.select("span[data-mce-type=bookmark]",e).length>0)&&r},kt=(t,e)=>t.isChildOf(e,t.getRoot()),Tt=t=>e=>e.options.get(t),At=Tt("lists_indent_on_tab"),wt=Tt("forced_root_block"),Dt=Tt("forced_root_block_attrs"),Et=(t,e)=>{const n=t.dom,r=t.schema.getBlockElements(),o=n.createFragment(),s=wt(t),i=Dt(t);let a,l,d=!1;for(l=n.create(s,i),Lt(e.firstChild,r)||o.appendChild(l);a=e.firstChild;){const t=a.nodeName;d||"SPAN"===t&&"bookmark"===a.getAttribute("data-mce-type")||(d=!0),Lt(a,r)?(o.appendChild(a),l=null):(l||(l=n.create(s,i),o.appendChild(l)),l.appendChild(a))}return!d&&l&&l.appendChild(n.create("br",{"data-mce-bogus":"1"})),o},Bt=dt.DOM,xt=H("dd"),It=H("dt"),Pt=(t,e)=>{var n;xt(e)?lt(e,"dt"):It(e)&&(n=e,g.from(n.dom.parentElement).map(R)).each((n=>((t,e,n)=>{const r=Bt.select('span[data-mce-type="bookmark"]',e),o=Et(t,n),s=Bt.createRng();s.setStartAfter(n),s.setEndAfter(e);const i=s.extractContents();for(let e=i.firstChild;e;e=e.firstChild)if("LI"===e.nodeName&&t.dom.isEmpty(e)){Bt.remove(e);break}t.dom.isEmpty(i)||Bt.insertAfter(i,e),Bt.insertAfter(o,e);const a=n.parentElement;a&&Ot(t.dom,a)&&(t=>{const e=t.parentNode;e&&ct.each(r,(t=>{e.insertBefore(t,n.parentNode)})),Bt.remove(t)})(a),Bt.remove(n),Ot(t.dom,e)&&Bt.remove(e)})(t,n.dom,e.dom)))},Mt=t=>{It(t)&<(t,"dd")},Rt=(t,e)=>{if(pt(t))return{container:t,offset:e};const n=Y.getNode(t,e);return pt(n)?{container:n,offset:e>=t.childNodes.length?n.data.length:0}:n.previousSibling&&pt(n.previousSibling)?{container:n.previousSibling,offset:n.previousSibling.data.length}:n.nextSibling&&pt(n.nextSibling)?{container:n.nextSibling,offset:0}:{container:t,offset:e}},Ut=t=>{const e=t.cloneRange(),n=Rt(t.startContainer,t.startOffset);e.setStart(n.container,n.offset);const r=Rt(t.endContainer,t.endOffset);return e.setEnd(r.container,r.offset),e},$t=["OL","UL","DL"],_t=$t.join(","),Ht=(t,e)=>{const n=e||t.selection.getStart(!0);return t.dom.getParent(n,_t,Kt(t,n))},jt=t=>{const e=t.selection.getSelectedBlocks();return N(((t,e)=>{const n=ct.map(e,(e=>t.dom.getParent(e,"li,dd,dt",Kt(t,e))||e));return B(n)})(t,e),vt)},Ft=(t,e)=>{const n=t.dom.getParents(e,"TD,TH");return n.length>0?n[0]:t.getBody()},Kt=(t,e)=>{const n=t.dom.getParents(e,t.dom.isBlock),r=k(n,(e=>{return n=t.schema,!ht(r=e)&&!vt(r)&&C($t,(t=>n.isValidChild(r.nodeName,t)));var n,r}));return r.getOr(t.getBody())},Vt=(t,e)=>{const n=t.dom.getParents(e,"ol,ul",Kt(t,e));return E(n)},zt=(t,e)=>{const n=b(e,(e=>Vt(t,e).getOr(e)));return B(n)},Qt=t=>/\btox\-/.test(t.className),qt=(t,e)=>O(t,ht,bt).exists((t=>t.nodeName===e&&!Qt(t))),Wt=(t,e)=>null!==e&&"false"===t.dom.getContentEditableParent(e),Zt=(t,e)=>{const n=t.dom.getParent(e,"ol,ul,dl");return Wt(t,n)},Gt=(t,e)=>{const n=t.selection.getNode();return e({parents:t.dom.getParents(n),element:n}),t.on("NodeChange",e),()=>t.off("NodeChange",e)},Jt=(t,e,n)=>t.dispatch("ListMutation",{action:e,element:n}),Xt=(Yt=/^\s+|\s+$/g,t=>t.replace(Yt,""));var Yt;const te=(t,e,n)=>{((t,e,n)=>{if(!r(n))throw console.error("Invalid call to CSS.set. Property ",e,":: Value ",n,":: Element ",t),new Error("CSS value must be a string: "+n);(t=>void 0!==t.style&&l(t.style.getPropertyValue))(t)&&t.style.setProperty(e,n)})(t.dom,e,n)},ee=(t,e)=>{Z(t.item,e.list)},ne=(t,e)=>{const n={list:M(e,t),item:M("li",t)};return Z(n.list,n.item),n},re=t=>((t,e)=>{const n=t.dom;if(1!==n.nodeType)return!1;{const t=n;if(void 0!==t.matches)return t.matches(e);if(void 0!==t.msMatchesSelector)return t.msMatchesSelector(e);if(void 0!==t.webkitMatchesSelector)return t.webkitMatchesSelector(e);if(void 0!==t.mozMatchesSelector)return t.mozMatchesSelector(e);throw new Error("Browser lacks native selectors")}})(t,"OL,UL"),oe=t=>V(t).exists(re),se=t=>t.depth>0,ie=t=>t.isSelected,ae=t=>{const e=F(t),n=z(t).exists(re)?e.slice(0,-1):e;return b(n,at)},le=t=>(S(t,((e,n)=>{((t,e)=>{const n=t[e].depth,r=t=>t.depth===n&&!t.dirty,o=t=>t.depthO(t.slice(e+1),r,o)))})(t,n).fold((()=>{e.dirty&&(t=>{t.listAttributes=((t,e)=>{const n={};var r;return((t,e,n,r)=>{ot(t,((t,o)=>{(e(t,o)?n:r)(t,o)}))})(t,e,(r=n,(t,e)=>{r[e]=t}),c),n})(t.listAttributes,((t,e)=>"start"!==e))})(e)}),(t=>{return r=t,(n=e).listType=r.listType,void(n.listAttributes={...r.listAttributes});var n,r}))})),t),de=(t,e,n,r)=>V(r).filter(re).fold((()=>{e.each((t=>{U(t.start,r)&&n.set(!0)}));const o=((t,e,n)=>j(t).filter(_).map((r=>({depth:e,dirty:!1,isSelected:n,content:ae(t),itemAttributes:it(t),listAttributes:it(r),listType:$(r)}))))(r,t,n.get());e.each((t=>{U(t.end,r)&&n.set(!1)}));const s=z(r).filter(re).map((r=>ce(t,e,n,r))).getOr([]);return o.toArray().concat(s)}),(r=>ce(t,e,n,r))),ce=(t,e,n,r)=>T(F(r),(r=>(re(r)?ce:de)(t+1,e,n,r))),ue=(t,e)=>{const n=le(e);return((t,e)=>{const n=L(e,((e,n)=>n.depth>e.length?((t,e,n)=>{const r=((t,e,n)=>{const r=[];for(let o=0;o{for(let e=1;e{for(let e=0;e{st(t.list,e.listAttributes),st(t.item,e.itemAttributes),G(t.item,e.content)}))})(r,n),o=r,I(E(e),D(o),ee),e.concat(r)})(t,e,n):((t,e,n)=>{const r=e.slice(0,n.depth);return E(r).each((e=>{const r=((t,e,n)=>{const r=M("li",t);return st(r,e),G(r,n),r})(t,n.itemAttributes,n.content);((t,e)=>{Z(t.list,e),t.item=e})(e,r),((t,e)=>{$(t.list)!==e.listType&&(t.list=lt(t.list,e.listType)),st(t.list,e.listAttributes)})(e,n)})),r})(t,e,n)),[]);return D(n).map((t=>t.list))})(t.contentDocument,n).toArray()},me=(t,e,n)=>{const r=((t,e)=>{const n=(t=>{let e=!1;return{get:()=>e,set:t=>{e=t}}})();return b(t,(t=>({sourceList:t,entries:ce(0,e,n,t)})))})(e,(t=>{const e=b(jt(t),R);return I(k(e,m(oe)),k(A(e),m(oe)),((t,e)=>({start:t,end:e})))})(t));S(r,(e=>{((t,e)=>{S(N(t,ie),(t=>((t,e)=>{switch(t){case"Indent":e.depth++;break;case"Outdent":e.depth--;break;case"Flatten":e.depth=0}e.dirty=!0})(e,t)))})(e.entries,n);const r=((t,e)=>T(((t,e)=>{if(0===t.length)return[];{let n=e(t[0]);const r=[];let o=[];for(let s=0,i=t.length;sD(e).exists(se)?ue(t,e):((t,e)=>{const n=le(e);return b(n,(e=>{const n=((t,e)=>{const n=document.createDocumentFragment();return S(t,(t=>{n.appendChild(t.dom)})),R(n)})(e.content);return R(Et(t,n.dom))}))})(t,e))))(t,e.entries);var o;S(r,(e=>{Jt(t,"Indent"===n?"IndentList":"OutdentList",e.dom)})),o=e.sourceList,S(r,(t=>{W(o,t)})),X(e.sourceList)}))},pe=(t,e)=>{const n=nt((t=>{const e=(t=>{const e=Vt(t,t.selection.getStart()),n=N(t.selection.getSelectedBlocks(),ft);return e.toArray().concat(n)})(t);return zt(t,e)})(t)),r=nt((t=>N(jt(t),Ct))(t));let o=!1;if(n.length||r.length){const s=t.selection.getBookmark();me(t,n,e),((t,e,n)=>{S(n,"Indent"===e?Mt:e=>Pt(t,e))})(t,e,r),t.selection.moveToBookmark(s),t.selection.setRng(Ut(t.selection.getRng())),t.nodeChanged(),o=!0}return o},ge=(t,e)=>!(t=>{const e=Ht(t);return Wt(t,e)})(t)&&pe(t,e),he=t=>ge(t,"Indent"),fe=t=>ge(t,"Outdent"),ye=t=>ge(t,"Flatten");var ve=tinymce.util.Tools.resolve("tinymce.dom.BookmarkManager");const Ce=dt.DOM,be=t=>{const e={},n=n=>{let r=t[n?"startContainer":"endContainer"],o=t[n?"startOffset":"endOffset"];if(gt(r)){const t=Ce.create("span",{"data-mce-type":"bookmark"});r.hasChildNodes()?(o=Math.min(o,r.childNodes.length-1),n?r.insertBefore(t,r.childNodes[o]):Ce.insertAfter(t,r.childNodes[o])):r.appendChild(t),r=t,o=0}e[n?"startContainer":"endContainer"]=r,e[n?"startOffset":"endOffset"]=o};return n(!0),t.collapsed||n(),e},Se=t=>{const e=e=>{let n=t[e?"startContainer":"endContainer"],r=t[e?"startOffset":"endOffset"];if(n){if(gt(n)&&n.parentNode){const t=n;r=(t=>{var e;let n=null===(e=t.parentNode)||void 0===e?void 0:e.firstChild,r=0;for(;n;){if(n===t)return r;gt(n)&&"bookmark"===n.getAttribute("data-mce-type")||r++,n=n.nextSibling}return-1})(n),n=n.parentNode,Ce.remove(t),!n.hasChildNodes()&&Ce.isBlock(n)&&n.appendChild(Ce.create("br"))}t[e?"startContainer":"endContainer"]=n,t[e?"startOffset":"endOffset"]=r}};e(!0),e();const n=Ce.createRng();return n.setStart(t.startContainer,t.startOffset),t.endContainer&&n.setEnd(t.endContainer,t.endOffset),Ut(n)},Ne=t=>{switch(t){case"UL":return"ToggleUlList";case"OL":return"ToggleOlList";case"DL":return"ToggleDLList"}},Le=(t,e)=>{ct.each(e,((e,n)=>{t.setAttribute(n,e)}))},Oe=(t,e,n)=>{((t,e,n)=>{const r=n["list-style-type"]?n["list-style-type"]:null;t.setStyle(e,"list-style-type",r)})(t,e,n),((t,e,n)=>{Le(e,n["list-attributes"]),ct.each(t.select("li",e),(t=>{Le(t,n["list-item-attributes"])}))})(t,e,n)},ke=(t,e,n,r)=>{let o=e[n?"startContainer":"endContainer"];const s=e[n?"startOffset":"endOffset"];for(gt(o)&&(o=o.childNodes[Math.min(s,o.childNodes.length-1)]||o),!n&&St(o.nextSibling)&&(o=o.nextSibling);o.parentNode!==r;){const e=o.parentNode;if(Nt(t,o))return o;if(/^(TD|TH)$/.test(e.nodeName))return o;o=e}return o},Te=(t,e,n)=>{const r=t.selection.getRng();let o="LI";const s=Kt(t,t.selection.getStart(!0)),i=t.dom;if("false"===i.getContentEditable(t.selection.getNode()))return;"DL"===(e=e.toUpperCase())&&(o="DT");const a=be(r),l=((t,e,n)=>{const r=[],o=t.dom,s=ke(t,e,!0,n),i=ke(t,e,!1,n);let a;const l=[];for(let t=s;t&&(l.push(t),t!==i);t=t.nextSibling);return ct.each(l,(e=>{var s;if(Nt(t,e))return r.push(e),void(a=null);if(o.isBlock(e)||St(e))return St(e)&&o.remove(e),void(a=null);const i=e.nextSibling;ve.isBookmarkNode(e)&&(ht(i)||Nt(t,i)||!i&&e.parentNode===n)?a=null:(a||(a=o.create("p"),null===(s=e.parentNode)||void 0===s||s.insertBefore(a,e),r.push(a)),a.appendChild(e))})),r})(t,r,s);ct.each(l,(r=>{let s;const a=r.previousSibling,l=r.parentNode;vt(l)||(a&&ht(a)&&a.nodeName===e&&((t,e,n)=>{const r=t.getStyle(e,"list-style-type");let o=n?n["list-style-type"]:"";return o=null===o?"":o,r===o})(i,a,n)?(s=a,r=i.rename(r,o),a.appendChild(r)):(s=i.create(e),l.insertBefore(s,r),s.appendChild(r),r=i.rename(r,o)),((t,e,n)=>{ct.each(["margin","margin-right","margin-bottom","margin-left","margin-top","padding","padding-right","padding-bottom","padding-left","padding-top"],(n=>t.setStyle(e,n,"")))})(i,r),Oe(i,s,n),we(t.dom,s))})),t.selection.setRng(Se(a))},Ae=(t,e,n)=>{return((t,e)=>ht(t)&&t.nodeName===(null==e?void 0:e.nodeName))(e,n)&&((t,e,n)=>t.getStyle(e,"list-style-type",!0)===t.getStyle(n,"list-style-type",!0))(t,e,n)&&(r=n,e.className===r.className);var r},we=(t,e)=>{let n,r=e.nextSibling;if(Ae(t,e,r)){const o=r;for(;n=o.firstChild;)e.appendChild(n);t.remove(o)}if(r=e.previousSibling,Ae(t,e,r)){const o=r;for(;n=o.lastChild;)e.insertBefore(n,e.firstChild);t.remove(o)}},De=t=>"list-style-type"in t,Ee=(t,e,n)=>{const r=Ht(t);if(Zt(t,r))return;const s=(t=>{const e=Ht(t),n=t.selection.getSelectedBlocks();return((t,e)=>a(t)&&1===e.length&&e[0]===t)(e,n)?(t=>N(t.querySelectorAll(_t),ht))(e):N(n,(t=>ht(t)&&e!==t))})(t),i=o(n)?n:{};s.length>0?((t,e,n,r,o)=>{const s=ht(e);if(s&&e.nodeName===r&&!De(o))ye(t);else{Te(t,r,o);const i=be(t.selection.getRng()),a=s?[e,...n]:n;ct.each(a,(e=>{((t,e,n,r)=>{if(e.nodeName!==n){const o=t.dom.rename(e,n);Oe(t.dom,o,r),Jt(t,Ne(n),o)}else Oe(t.dom,e,r),Jt(t,Ne(n),e)})(t,e,r,o)})),t.selection.setRng(Se(i))}})(t,r,s,e,i):((t,e,n,r)=>{if(e!==t.getBody())if(e)if(e.nodeName!==n||De(r)||Qt(e)){const o=be(t.selection.getRng());Oe(t.dom,e,r);const s=t.dom.rename(e,n);we(t.dom,s),t.selection.setRng(Se(o)),Te(t,n,r),Jt(t,Ne(n),s)}else ye(t);else Te(t,n,r),Jt(t,Ne(n),e)})(t,r,e,i)},Be=dt.DOM,xe=(t,e)=>{const n=ct.grep(t.select("ol,ul",e));ct.each(n,(e=>{((t,e)=>{const n=e.parentElement;if(n&&"LI"===n.nodeName&&n.firstChild===e){const r=n.previousSibling;r&&"LI"===r.nodeName?(r.appendChild(e),Ot(t,n)&&Be.remove(n)):Be.setStyle(n,"listStyleType","none")}if(ht(n)){const t=n.previousSibling;t&&"LI"===t.nodeName&&t.appendChild(e)}})(t,e)}))},Ie=(t,e,n,r)=>{let o=e.startContainer;const s=e.startOffset;if(pt(o)&&(n?s0))return o;const i=t.schema.getNonEmptyElements();gt(o)&&(o=Y.getNode(o,s));const a=new tt(o,r);n&&((t,e)=>!!St(e)&&t.isBlock(e.nextSibling)&&!St(e.previousSibling))(t.dom,o)&&a.next();const l=n?a.next.bind(a):a.prev2.bind(a);for(;o=l();){if("LI"===o.nodeName&&!o.hasChildNodes())return o;if(i[o.nodeName])return o;if(pt(o)&&o.data.length>0)return o}return null},Pe=(t,e)=>{const n=e.childNodes;return 1===n.length&&!ht(n[0])&&t.isBlock(n[0])},Me=(t,e,n)=>{let r;const o=e.parentNode;if(!kt(t,e)||!kt(t,n))return;ht(n.lastChild)&&(r=n.lastChild),o===n.lastChild&&St(o.previousSibling)&&t.remove(o.previousSibling);const s=n.lastChild;s&&St(s)&&e.hasChildNodes()&&t.remove(s),Ot(t,n,!0)&&J(R(n)),((t,e,n)=>{let r;const o=Pe(t,n)?n.firstChild:n;if(((t,e)=>{Pe(t,e)&&t.remove(e.firstChild,!0)})(t,e),!Ot(t,e,!0))for(;r=e.firstChild;)o.appendChild(r)})(t,e,n),r&&n.appendChild(r);const i=((t,e)=>{const n=t.dom,r=e.dom;return n!==r&&n.contains(r)})(R(n),R(e))?t.getParents(e,ht,n):[];t.remove(e),S(i,(e=>{Ot(t,e)&&e!==t.getRoot()&&t.remove(e)}))},Re=(t,e)=>{const n=t.dom,r=t.selection,o=r.getStart(),s=Ft(t,o),i=n.getParent(r.getStart(),"LI",s);if(i){const o=i.parentElement;if(o===t.getBody()&&Ot(n,o))return!0;const a=Ut(r.getRng()),l=n.getParent(Ie(t,a,e,s),"LI",s);if(l&&l!==i)return t.undoManager.transact((()=>{var n,r;e?((t,e,n,r)=>{const o=t.dom;if(o.isEmpty(r))((t,e,n)=>{J(R(n)),Me(t.dom,e,n),t.selection.setCursorLocation(n,0)})(t,n,r);else{const s=be(e);Me(o,n,r),t.selection.setRng(Se(s))}})(t,a,l,i):(null===(r=(n=i).parentNode)||void 0===r?void 0:r.firstChild)===n?fe(t):((t,e,n,r)=>{const o=be(e);Me(t.dom,n,r);const s=Se(o);t.selection.setRng(s)})(t,a,i,l)})),!0;if(!l&&!e&&0===a.startOffset&&0===a.endOffset)return t.undoManager.transact((()=>{ye(t)})),!0}return!1},Ue=t=>{const e=t.selection.getStart(),n=Ft(t,e);return t.dom.getParent(e,"LI,DT,DD",n)||jt(t).length>0},$e=(t,e)=>{const n=t.selection;return!Zt(t,n.getNode())&&(n.isCollapsed()?((t,e)=>Re(t,e)||((t,e)=>{const n=t.dom,r=t.selection.getStart(),o=Ft(t,r),s=n.getParent(r,n.isBlock,o);if(s&&n.isEmpty(s)){const r=Ut(t.selection.getRng()),i=n.getParent(Ie(t,r,e,o),"LI",o);if(i){const a=t=>v(["td","th","caption"],$(t)),l=t=>t.dom===o;return!!((t,e,n=u)=>I(t,e,n).getOr(t.isNone()&&e.isNone()))(q(R(i),a,l),q(R(r.startContainer),a,l),U)&&(t.undoManager.transact((()=>{((t,e,n)=>{const r=t.getParent(e.parentNode,t.isBlock,n);t.remove(e),r&&t.isEmpty(r)&&t.remove(r)})(n,s,o),we(n,i.parentNode),t.selection.select(i,!0),t.selection.collapse(e)})),!0)}}return!1})(t,e))(t,e):(t=>!!Ue(t)&&(t.undoManager.transact((()=>{t.execCommand("Delete"),xe(t.dom,t.getBody())})),!0))(t))},_e=t=>{const e=A(Xt(t).split("")),n=b(e,((t,e)=>{const n=t.toUpperCase().charCodeAt(0)-"A".charCodeAt(0)+1;return Math.pow(26,e)*n}));return L(n,((t,e)=>t+e),0)},He=t=>{if(--t<0)return"";{const e=t%26,n=Math.floor(t/26);return He(n)+String.fromCharCode("A".charCodeAt(0)+e)}},je=t=>{const e=parseInt(t.start,10);return x(t.listStyleType,"upper-alpha")?He(e):x(t.listStyleType,"lower-alpha")?He(e).toLowerCase():t.start},Fe=(t,e)=>()=>{const n=Ht(t);return a(n)&&n.nodeName===e},Ke=t=>{t.addCommand("mceListProps",(()=>{(t=>{const e=Ht(t);yt(e)&&!Zt(t,e)&&t.windowManager.open({title:"List Properties",body:{type:"panel",items:[{type:"input",name:"start",label:"Start list at number",inputMode:"numeric"}]},initialData:{start:je({start:t.dom.getAttrib(e,"start","1"),listStyleType:g.from(t.dom.getStyle(e,"list-style-type"))})},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],onSubmit:e=>{(t=>{switch((t=>/^[0-9]+$/.test(t)?2:/^[A-Z]+$/.test(t)?0:/^[a-z]+$/.test(t)?1:t.length>0?4:3)(t)){case 2:return g.some({listStyleType:g.none(),start:t});case 0:return g.some({listStyleType:g.some("upper-alpha"),start:_e(t).toString()});case 1:return g.some({listStyleType:g.some("lower-alpha"),start:_e(t).toString()});case 3:return g.some({listStyleType:g.none(),start:""});case 4:return g.none()}})(e.getData().start).each((e=>{t.execCommand("mceListUpdate",!1,{attrs:{start:"1"===e.start?"":e.start},styles:{"list-style-type":e.listStyleType.getOr("")}})})),e.close()}})})(t)}))},Ve=(t,e)=>n=>Gt(t,(r=>{n.setActive(qt(r.parents,e)),n.setEnabled(!Zt(t,r.element))})),ze=(t,e)=>n=>Gt(t,(r=>n.setEnabled(qt(r.parents,e)&&!Zt(t,r.element))));t.add("lists",(t=>((t=>{(0,t.options.register)("lists_indent_on_tab",{processor:"boolean",default:!0})})(t),t.hasPlugin("rtc",!0)?Ke(t):((t=>{At(t)&&(t=>{t.on("keydown",(e=>{e.keyCode!==et.TAB||et.metaKeyPressed(e)||t.undoManager.transact((()=>{(e.shiftKey?fe(t):he(t))&&e.preventDefault()}))}))})(t),(t=>{t.on("ExecCommand",(e=>{const n=e.command.toLowerCase();"delete"!==n&&"forwarddelete"!==n||!Ue(t)||xe(t.dom,t.getBody())})),t.on("keydown",(e=>{e.keyCode===et.BACKSPACE?$e(t,!1)&&e.preventDefault():e.keyCode===et.DELETE&&$e(t,!0)&&e.preventDefault()}))})(t)})(t),(t=>{t.on("BeforeExecCommand",(e=>{const n=e.command.toLowerCase();"indent"===n?he(t):"outdent"===n&&fe(t)})),t.addCommand("InsertUnorderedList",((e,n)=>{Ee(t,"UL",n)})),t.addCommand("InsertOrderedList",((e,n)=>{Ee(t,"OL",n)})),t.addCommand("InsertDefinitionList",((e,n)=>{Ee(t,"DL",n)})),t.addCommand("RemoveList",(()=>{ye(t)})),Ke(t),t.addCommand("mceListUpdate",((e,n)=>{o(n)&&((t,e)=>{const n=Ht(t);null===n||Zt(t,n)||t.undoManager.transact((()=>{o(e.styles)&&t.dom.setStyles(n,e.styles),o(e.attrs)&&ot(e.attrs,((e,r)=>t.dom.setAttrib(n,r,e)))}))})(t,n)})),t.addQueryStateHandler("InsertUnorderedList",Fe(t,"UL")),t.addQueryStateHandler("InsertOrderedList",Fe(t,"OL")),t.addQueryStateHandler("InsertDefinitionList",Fe(t,"DL"))})(t)),(t=>{const e=e=>()=>t.execCommand(e);t.hasPlugin("advlist")||(t.ui.registry.addToggleButton("numlist",{icon:"ordered-list",active:!1,tooltip:"Numbered list",onAction:e("InsertOrderedList"),onSetup:Ve(t,"OL")}),t.ui.registry.addToggleButton("bullist",{icon:"unordered-list",active:!1,tooltip:"Bullet list",onAction:e("InsertUnorderedList"),onSetup:Ve(t,"UL")}))})(t),(t=>{const e={text:"List properties...",icon:"ordered-list",onAction:()=>t.execCommand("mceListProps"),onSetup:ze(t,"OL")};t.ui.registry.addMenuItem("listprops",e),t.ui.registry.addContextMenu("lists",{update:e=>{const n=Ht(t,e);return yt(n)?["listprops"]:[]}})})(t),(t=>({backspaceDelete:e=>{$e(t,e)}}))(t))))}(); \ No newline at end of file diff --git a/public/plugins/tinymce/plugins/media/plugin.min.js b/public/plugins/tinymce/plugins/media/plugin.min.js new file mode 100644 index 000000000..4fbf69f6c --- /dev/null +++ b/public/plugins/tinymce/plugins/media/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.3.1 (2022-12-06) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(r=a=e,(o=String).prototype.isPrototypeOf(r)||(null===(s=a.constructor)||void 0===s?void 0:s.name)===o.name)?"string":t;var r,a,o,s})(t)===e,r=t("string"),a=t("object"),o=t("array"),s=e=>!(e=>null==e)(e);class i{constructor(e,t){this.tag=e,this.value=t}static some(e){return new i(!0,e)}static none(){return i.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?i.some(e(this.value)):i.none()}bind(e){return this.tag?e(this.value):i.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:i.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return s(e)?i.some(e):i.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}i.singletonNone=new i(!1);const n=Array.prototype.push,c=(e,t)=>{for(let r=0,a=e.length;r{const t=[];for(let r=0,a=e.length;rh(e,t)?i.from(e[t]):i.none(),h=(e,t)=>u.call(e,t),p=e=>t=>t.options.get(e),g=p("audio_template_callback"),b=p("video_template_callback"),w=p("iframe_template_callback"),v=p("media_live_embeds"),f=p("media_filter_html"),y=p("media_url_resolver"),x=p("media_alt_source"),_=p("media_poster"),j=p("media_dimensions");var k=tinymce.util.Tools.resolve("tinymce.util.Tools"),O=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),A=tinymce.util.Tools.resolve("tinymce.html.DomParser");const S=O.DOM,C=e=>e.replace(/px$/,""),D=e=>{const t=e.attr("style"),r=t?S.parseStyle(t):{};return{type:"ephox-embed-iri",source:e.attr("data-ephox-embed-iri"),altsource:"",poster:"",width:d(r,"max-width").map(C).getOr(""),height:d(r,"max-height").map(C).getOr("")}},T=(e,t)=>{let r={};for(let a=A({validate:!1,forced_root_block:!1},t).parse(e);a;a=a.walk())if(1===a.type){const e=a.name;if(a.attr("data-ephox-embed-iri")){r=D(a);break}r.source||"param"!==e||(r.source=a.attr("movie")),"iframe"!==e&&"object"!==e&&"embed"!==e&&"video"!==e&&"audio"!==e||(r.type||(r.type=e),r=k.extend(a.attributes.map,r)),"script"===e&&(r={type:"script",source:a.attr("src")}),"source"===e&&(r.source?r.altsource||(r.altsource=a.attr("src")):r.source=a.attr("src")),"img"!==e||r.poster||(r.poster=a.attr("src"))}return r.source=r.source||r.src||"",r.altsource=r.altsource||"",r.poster=r.poster||"",r},$=e=>{var t;const r=null!==(t=e.toLowerCase().split(".").pop())&&void 0!==t?t:"";return d({mp3:"audio/mpeg",m4a:"audio/x-m4a",wav:"audio/wav",mp4:"video/mp4",webm:"video/webm",ogg:"video/ogg",swf:"application/x-shockwave-flash"},r).getOr("")};var z=tinymce.util.Tools.resolve("tinymce.html.Node"),M=tinymce.util.Tools.resolve("tinymce.html.Serializer");const F=(e,t={})=>A({forced_root_block:!1,validate:!1,allow_conditional_comments:!0,...t},e),N=O.DOM,R=e=>/^[0-9.]+$/.test(e)?e+"px":e,U=(e,t)=>{const r=t.attr("style"),a=r?N.parseStyle(r):{};s(e.width)&&(a["max-width"]=R(e.width)),s(e.height)&&(a["max-height"]=R(e.height)),t.attr("style",N.serializeStyle(a))},P=["source","altsource"],E=(e,t,r,a)=>{let o=0,s=0;const i=F(a);i.addNodeFilter("source",(e=>o=e.length));const n=i.parse(e);for(let e=n;e;e=e.walk())if(1===e.type){const a=e.name;if(e.attr("data-ephox-embed-iri")){U(t,e);break}switch(a){case"video":case"object":case"embed":case"img":case"iframe":void 0!==t.height&&void 0!==t.width&&(e.attr("width",t.width),e.attr("height",t.height))}if(r)switch(a){case"video":e.attr("poster",t.poster),e.attr("src",null);for(let r=o;r<2;r++)if(t[P[r]]){const a=new z("source",1);a.attr("src",t[P[r]]),a.attr("type",t[P[r]+"mime"]||null),e.append(a)}break;case"iframe":e.attr("src",t.source);break;case"object":const r=e.getAll("img").length>0;if(t.poster&&!r){e.attr("src",t.poster);const r=new z("img",1);r.attr("src",t.poster),r.attr("width",t.width),r.attr("height",t.height),e.append(r)}break;case"source":if(s<2&&(e.attr("src",t[P[s]]),e.attr("type",t[P[s]+"mime"]||null),!t[P[s]])){e.remove();continue}s++;break;case"img":t.poster||e.remove()}}return M({},a).serialize(n)},L=[{regex:/youtu\.be\/([\w\-_\?&=.]+)/i,type:"iframe",w:560,h:314,url:"www.youtube.com/embed/$1",allowFullscreen:!0},{regex:/youtube\.com(.+)v=([^&]+)(&([a-z0-9&=\-_]+))?/i,type:"iframe",w:560,h:314,url:"www.youtube.com/embed/$2?$4",allowFullscreen:!0},{regex:/youtube.com\/embed\/([a-z0-9\?&=\-_]+)/i,type:"iframe",w:560,h:314,url:"www.youtube.com/embed/$1",allowFullscreen:!0},{regex:/vimeo\.com\/([0-9]+)/,type:"iframe",w:425,h:350,url:"player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc",allowFullscreen:!0},{regex:/vimeo\.com\/(.*)\/([0-9]+)/,type:"iframe",w:425,h:350,url:"player.vimeo.com/video/$2?title=0&byline=0",allowFullscreen:!0},{regex:/maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/,type:"iframe",w:425,h:350,url:'maps.google.com/maps/ms?msid=$2&output=embed"',allowFullscreen:!1},{regex:/dailymotion\.com\/video\/([^_]+)/,type:"iframe",w:480,h:270,url:"www.dailymotion.com/embed/video/$1",allowFullscreen:!0},{regex:/dai\.ly\/([^_]+)/,type:"iframe",w:480,h:270,url:"www.dailymotion.com/embed/video/$1",allowFullscreen:!0}],I=(e,t)=>{const r=(e=>{const t=e.match(/^(https?:\/\/|www\.)(.+)$/i);return t&&t.length>1?"www."===t[1]?"https://":t[1]:"https://"})(t),a=e.regex.exec(t);let o=r+e.url;if(s(a))for(let e=0;ea[e]?a[e]:""));return o.replace(/\?$/,"")},B=(e,t)=>{var r;const a=k.extend({},t);if(!a.source&&(k.extend(a,T(null!==(r=a.embed)&&void 0!==r?r:"",e.schema)),!a.source))return"";a.altsource||(a.altsource=""),a.poster||(a.poster=""),a.source=e.convertURL(a.source,"source"),a.altsource=e.convertURL(a.altsource,"source"),a.sourcemime=$(a.source),a.altsourcemime=$(a.altsource),a.poster=e.convertURL(a.poster,"poster");const o=(e=>{const t=L.filter((t=>t.regex.test(e)));return t.length>0?k.extend({},t[0],{url:I(t[0],e)}):null})(a.source);if(o&&(a.source=o.url,a.type=o.type,a.allowfullscreen=o.allowFullscreen,a.width=a.width||String(o.w),a.height=a.height||String(o.h)),a.embed)return E(a.embed,a,!0,e.schema);{const t=g(e),r=b(e),o=w(e);return a.width=a.width||"300",a.height=a.height||"150",k.each(a,((t,r)=>{a[r]=e.dom.encode(""+t)})),"iframe"===a.type?((e,t)=>{if(t)return t(e);{const t=e.allowfullscreen?' allowFullscreen="1"':"";return'"}})(a,o):"application/x-shockwave-flash"===a.sourcemime?(e=>{let t='';return e.poster&&(t+=''),t+="",t})(a):-1!==a.sourcemime.indexOf("audio")?((e,t)=>t?t(e):'")(a,t):"script"===a.type?(e=>'