namespace HPHP { static class DateExtension : public Extension { public: DateExtension() : Extension("date") { } void moduleInit() { IniSetting::Bind( "date.timezone", g_context->getDefaultTimeZone().c_str(), dateTimezoneIniCallback, nullptr ); } private: static bool dateTimezoneIniCallback(const HPHP::String& value, void *p) { assert(p == nullptr); if (value.empty()) { return false; } return f_date_default_timezone_set(value); } } s_date_extension; /////////////////////////////////////////////////////////////////////////////// // constants const StaticString q_DateTime$$ATOM(LITSTR_INIT("Y-m-d\\TH:i:sP")); const StaticString q_DateTime$$COOKIE(LITSTR_INIT("l, d-M-y H:i:s T")); const StaticString q_DateTime$$ISO8601(LITSTR_INIT("Y-m-d\\TH:i:sO")); const StaticString q_DateTime$$RFC822(LITSTR_INIT("D, d M y H:i:s O")); const StaticString q_DateTime$$RFC850(LITSTR_INIT("l, d-M-y H:i:s T")); const StaticString q_DateTime$$RFC1036(LITSTR_INIT("D, d M y H:i:s O")); const StaticString q_DateTime$$RFC1123(LITSTR_INIT("D, d M Y H:i:s O")); const StaticString q_DateTime$$RFC2822(LITSTR_INIT("D, d M Y H:i:s O")); const StaticString q_DateTime$$RFC3339(LITSTR_INIT("Y-m-d\\TH:i:sP")); const StaticString q_DateTime$$RSS(LITSTR_INIT("D, d M Y H:i:s O")); const StaticString q_DateTime$$W3C(LITSTR_INIT("Y-m-d\\TH:i:sP")); const int64_t q_DateTimeZone$$AFRICA = 1; const int64_t q_DateTimeZone$$AMERICA = 2; const int64_t q_DateTimeZone$$ANTARCTICA = 4; const int64_t q_DateTimeZone$$ARCTIC = 8; const int64_t q_DateTimeZone$$ASIA = 16; const int64_t q_DateTimeZone$$ATLANTIC = 32; const int64_t q_DateTimeZone$$AUSTRALIA = 64; const int64_t q_DateTimeZone$$EUROPE = 128; const int64_t q_DateTimeZone$$INDIAN = 256; const int64_t q_DateTimeZone$$PACIFIC = 512; const int64_t q_DateTimeZone$$UTC = 1024; const int64_t q_DateTimeZone$$ALL = 2047; const int64_t q_DateTimeZone$$ALL_WITH_BC = 4095; const int64_t q_DateTimeZone$$PER_COUNTRY = 4096; /////////////////////////////////////////////////////////////////////////////// // methods Object c_DateTime::t_add(CObjRef interval) { m_dt->add(c_DateInterval::unwrap(interval)); return this; } void c_DateTime::t___construct(const String& time /*= "now"*/, CObjRef timezone /*= null_object*/) { m_dt = NEWOBJ(DateTime)(TimeStamp::Current()); if (!time.empty()) { m_dt->fromString(time, c_DateTimeZone::unwrap(timezone)); } } Object c_DateTime::ti_createfromformat(const String& format, const String& time, CObjRef timezone /*= null_object */) { c_DateTime *datetime = NEWOBJ(c_DateTime); datetime->m_dt = NEWOBJ(DateTime); datetime->m_dt->fromString(time, c_DateTimeZone::unwrap(timezone), format.data()); return datetime; } Object c_DateTime::t_diff(CObjRef datetime2, bool absolute) { return c_DateInterval::wrap(m_dt->diff(c_DateTime::unwrap(datetime2), absolute)); } String c_DateTime::t_format(const String& format) { return m_dt->toString(format, false); } const StaticString s_warning_count("warning_count"), s_warnings("warnings"), s_error_count("error_count"), s_errors("errors"); Array c_DateTime::ti_getlasterrors() { Array errors = DateTime::getLastErrors(); Array warnings = DateTime::getLastWarnings(); Array ret = Array::Create(); ret.add(s_warning_count, warnings.size()); ret.add(s_warnings, warnings); ret.add(s_error_count, errors.size()); ret.add(s_errors, errors); return ret; } int64_t c_DateTime::t_getoffset() { return m_dt->offset(); } int64_t c_DateTime::t_gettimestamp() { return gettimestamp(); } int64_t c_DateTime::gettimestamp() const { bool err = false; return m_dt->toTimeStamp(err); } Variant c_DateTime::t_gettimezone() { SmartResource<TimeZone> tz = m_dt->timezone(); if (tz->isValid()) { return c_DateTimeZone::wrap(tz); } return false; } Object c_DateTime::t_modify(const String& modify) { m_dt->modify(modify); return this; } Object c_DateTime::t_setdate(int64_t year, int64_t month, int64_t day) { m_dt->setDate(year, month, day); return this; } Object c_DateTime::t_setisodate(int64_t year, int64_t week, int64_t day /*= 1*/) { m_dt->setISODate(year, week, day); return this; } Object c_DateTime::t_settime(int64_t hour, int64_t minute, int64_t second /*= 0*/) { m_dt->setTime(hour, minute, second); return this; } Object c_DateTime::t_settimestamp(int64_t unixtimestamp) { m_dt->fromTimeStamp(unixtimestamp, false); return this; } Object c_DateTime::t_settimezone(CObjRef timezone) { m_dt->setTimezone(c_DateTimeZone::unwrap(timezone)); return this; } Object c_DateTime::t_sub(CObjRef interval) { m_dt->sub(c_DateInterval::unwrap(interval)); return this; } c_DateTime* c_DateTime::Clone(ObjectData* obj) { c_DateTime* dt = static_cast<c_DateTime*>(obj->cloneImpl()); dt->m_dt = static_cast<c_DateTime*>(obj)->m_dt->cloneDateTime(); return dt; } void c_DateTimeZone::t___construct(const String& timezone) { m_tz = NEWOBJ(TimeZone)(timezone); if (!m_tz->isValid()) { std::string msg = "DateTimeZone::__construct(): Unknown or bad timezone ("; msg += timezone.data(); msg += ")"; throw Object(SystemLib::AllocExceptionObject(msg)); } } Array c_DateTimeZone::t_getlocation() { return m_tz->getLocation(); } String c_DateTimeZone::t_getname() { return m_tz->name(); } int64_t c_DateTimeZone::t_getoffset(CObjRef datetime) { bool error; int64_t ts = c_DateTime::unwrap(datetime)->toTimeStamp(error); return m_tz->offset(ts); } Array c_DateTimeZone::t_gettransitions() { return m_tz->transitions(); } Array c_DateTimeZone::ti_listabbreviations() { return TimeZone::GetAbbreviations(); } Array c_DateTimeZone::ti_listidentifiers() { return TimeZone::GetNames(); } c_DateTimeZone* c_DateTimeZone::Clone(ObjectData* obj) { c_DateTimeZone* dtz = static_cast<c_DateTimeZone*>(obj->cloneImpl()); dtz->m_tz = static_cast<c_DateTimeZone*>(obj)->m_tz->cloneTimeZone(); return dtz; } void c_DateInterval::t___construct(const String& interval_spec) { m_di = NEWOBJ(DateInterval)(interval_spec); if (!m_di->isValid()) { std::string msg = "DateInterval::__construct: Invalid interval ("; msg += interval_spec.data(); msg += ")"; throw Object(SystemLib::AllocExceptionObject(msg)); } } const StaticString s_y("y"), s_m("m"), s_d("d"), s_h("h"), s_i("i"), s_s("s"), s_invert("invert"), s_days("days"); Variant c_DateInterval::t___get(Variant member) { if (member.isString()) { if (same(member, s_y)) return m_di->getYears(); if (same(member, s_m)) return m_di->getMonths(); if (same(member, s_d)) return m_di->getDays(); if (same(member, s_h)) return m_di->getHours(); if (same(member, s_i)) return m_di->getMinutes(); if (same(member, s_s)) return m_di->getSeconds(); if (same(member, s_invert)) return m_di->isInverted(); if (same(member, s_days)) { if (m_di->haveTotalDays()) { return m_di->getTotalDays(); } else { return false; } } } std::string msg = "Undefined property '"; msg += member.toString().data(); msg += ") on DateInterval object"; throw Object(SystemLib::AllocExceptionObject(msg)); } Variant c_DateInterval::t___set(Variant member, Variant value) { if (member.isString()) { if (same(member, s_y)) { m_di->setYears(value.toInt64()); return uninit_null(); } if (same(member, s_m)) { m_di->setMonths(value.toInt64()); return uninit_null(); } if (same(member, s_d)) { m_di->setDays(value.toInt64()); return uninit_null(); } if (same(member, s_h)) { m_di->setHours(value.toInt64()); return uninit_null(); } if (same(member, s_i)) { m_di->setMinutes(value.toInt64()); return uninit_null(); } if (same(member, s_s)) { m_di->setSeconds(value.toInt64()); return uninit_null(); } if (same(member, s_invert)) { m_di->setInverted(value.toBoolean()); return uninit_null(); } if (same(member, s_days)) { m_di->setTotalDays(value.toInt64()); return uninit_null(); } } std::string msg = "Undefined property '"; msg += member.toString().data(); msg += ") on DateInterval object"; throw Object(SystemLib::AllocExceptionObject(msg)); } Object c_DateInterval::ti_createfromdatestring(const String& time) { SmartResource<DateInterval> di(NEWOBJ(DateInterval)(time, true)); return c_DateInterval::wrap(di); } String c_DateInterval::t_format(const String& format) { return m_di->format(format); } c_DateInterval* c_DateInterval::Clone(ObjectData* obj) { c_DateInterval *di = static_cast<c_DateInterval*>(obj->cloneImpl()); di->m_di = static_cast<c_DateInterval*>(obj)->m_di->cloneDateInterval(); return di; } /////////////////////////////////////////////////////////////////////////////// // timestamp Variant f_gettimeofday(bool return_float /* = false */) { if (return_float) { return TimeStamp::CurrentSecond(); } return TimeStamp::CurrentTime(); } Variant f_microtime(bool get_as_float /* = false */) { if (get_as_float) { return TimeStamp::CurrentSecond(); } return TimeStamp::CurrentMicroTime(); } int64_t f_time() { return time(0); } Variant f_mktime(int hour /* = INT_MAX */, int minute /* = INT_MAX */, int second /* = INT_MAX */, int month /* = INT_MAX */, int day /* = INT_MAX */, int year /* = INT_MAX */) { bool error; int64_t ts = TimeStamp::Get(error, hour, minute, second, month, day, year, false); if (error) return false; return ts; } Variant f_gmmktime(int hour /* = INT_MAX */, int minute /* = INT_MAX */, int second /* = INT_MAX */, int month /* = INT_MAX */, int day /* = INT_MAX */, int year /* = INT_MAX */) { bool error; int64_t ts = TimeStamp::Get(error, hour, minute, second, month, day, year, true); if (error) return false; return ts; } Variant f_idate(const String& format, int64_t timestamp /* = TimeStamp::Current() */) { if (format.size() != 1) { throw_invalid_argument("format: %s", format.data()); return false; } int64_t ret = DateTime(timestamp, false).toInteger(*format.data()); if (ret == -1) return false; return ret; } Variant f_date(const String& format, int64_t timestamp /* = TimeStamp::Current() */) { if (format.empty()) return ""; String ret = DateTime(timestamp, false).toString(format, false); if (ret.isNull()) return false; return ret; } Variant f_gmdate(const String& format, int64_t timestamp /* = TimeStamp::Current() */) { String ret = DateTime(timestamp, true).toString(format, false); if (ret.isNull()) return false; return ret; } Variant f_strftime(const String& format, int64_t timestamp /* = TimeStamp::Current() */) { String ret = DateTime(timestamp, false).toString(format, true); if (ret.isNull()) return false; return ret; } String f_gmstrftime(const String& format, int64_t timestamp /* = TimeStamp::Current() */) { String ret = DateTime(timestamp, true).toString(format, true); if (ret.isNull()) return false; return ret; } Array f_getdate(int64_t timestamp /* = TimeStamp::Current() */) { return DateTime(timestamp, false).toArray(DateTime::ArrayFormat::TimeMap); } Array f_localtime(int64_t timestamp /* = TimeStamp::Current() */, bool is_associative /* = false */) { DateTime::ArrayFormat format = is_associative ? DateTime::ArrayFormat::TmMap : DateTime::ArrayFormat::TmVector; return DateTime(timestamp, false).toArray(format); } Variant f_strptime(const String& date, const String& format) { Array ret = DateTime::ParseAsStrptime(format, date); if (ret.empty()) { return false; } return ret; } Variant f_strtotime(const String& input, int64_t timestamp /* = TimeStamp::Current() */) { if (input.empty()) { return false; } DateTime dt(timestamp); if (!dt.fromString(input, SmartResource<TimeZone>())) { return false; } bool error; return dt.toTimeStamp(error); } /////////////////////////////////////////////////////////////////////////////// // timezone String f_date_default_timezone_get() { return TimeZone::Current()->name(); } bool f_date_default_timezone_set(const String& name) { return TimeZone::SetCurrent(name); } Array f_timezone_identifiers_list() { return c_DateTimeZone::ti_listidentifiers(); } Array f_timezone_abbreviations_list() { return c_DateTimeZone::ti_listabbreviations(); } Variant f_timezone_name_from_abbr(const String& abbr, int gmtoffset /* = -1 */, bool isdst /* = true */) { String ret = TimeZone::AbbreviationToName(abbr, gmtoffset, isdst); if (ret.isNull()) { return false; } return ret; } Object f_timezone_open(const String& timezone) { c_DateTimeZone *ctz = NEWOBJ(c_DateTimeZone)(); Object ret(ctz); ctz->t___construct(timezone); return ret; } Array f_timezone_location_get(CObjRef timezone) { return timezone.getTyped<c_DateTimeZone>()->t_getlocation(); } String f_timezone_name_get(CObjRef object) { return object.getTyped<c_DateTimeZone>()->t_getname(); } int64_t f_timezone_offset_get(CObjRef object, CObjRef dt) { return object.getTyped<c_DateTimeZone>()->t_getoffset(dt); } Array f_timezone_transitions_get(CObjRef object) { return object.getTyped<c_DateTimeZone>()->t_gettransitions(); } String f_timezone_version_get() { return TimeZone::getVersion(); } /////////////////////////////////////////////////////////////////////////////// // datetime bool f_checkdate(int month, int day, int year) { return DateTime::IsValid(year, month, day); } Object f_date_add(CObjRef datetime, CObjRef interval) { return datetime.getTyped<c_DateTime>()-> t_add(interval.getTyped<c_DateInterval>()); } Object f_date_create_from_format(const String& format, const String& time, CObjRef timezone /* = null_object */) { return c_DateTime::ti_createfromformat(format, time, timezone); } Variant f_date_parse_from_format(const String& format, const String& date) { Array ret = DateTime::Parse(format, date); if (ret.empty()) { return false; } return ret; } Object f_date_create(const String& time /* = null_string */, CObjRef timezone /* = null_object */) { c_DateTime *cdt = NEWOBJ(c_DateTime)(); Object ret(cdt); cdt->t___construct(time, timezone); return ret; } void f_date_date_set(CObjRef object, int year, int month, int day) { object.getTyped<c_DateTime>()->t_setdate(year, month, day); } Object f_date_diff(CObjRef datetime, CObjRef datetime2, bool absolute /* = false */) { return datetime.getTyped<c_DateTime>()-> t_diff(datetime2.getTyped<c_DateTime>(), absolute); } void f_date_isodate_set(CObjRef object, int year, int week, int day /* = 1 */) { object.getTyped<c_DateTime>()->t_setisodate(year, week, day); } String f_date_format(CObjRef object, const String& format) { return object.getTyped<c_DateTime>()->t_format(format); } Array f_date_get_last_errors() { return c_DateTime::ti_getlasterrors(); } Object f_date_interval_create_from_date_string(const String& time) { return c_DateInterval::ti_createfromdatestring(time); } String f_date_interval_format(CObjRef interval, const String& format_spec) { return interval.getTyped<c_DateInterval>()->t_format(format_spec); } void f_date_modify(CObjRef object, const String& modify) { object.getTyped<c_DateTime>()->t_modify(modify); } int64_t f_date_offset_get(CObjRef object) { return object.getTyped<c_DateTime>()->t_getoffset(); } Variant f_date_parse(const String& date) { Array ret = DateTime::Parse(date); if (ret.empty()) { return false; } return ret; } void f_date_time_set(CObjRef object, int hour, int minute, int second /* = 0 */) { object.getTyped<c_DateTime>()->t_settime(hour, minute, second); } int64_t f_date_timestamp_get(CObjRef datetime) { return datetime.getTyped<c_DateTime>()->t_gettimestamp(); } Object f_date_timestamp_set(CObjRef datetime, int64_t timestamp) { return datetime.getTyped<c_DateTime>()-> t_settimestamp(timestamp); } Variant f_date_timezone_get(CObjRef object) { return object.getTyped<c_DateTime>()->t_gettimezone(); } void f_date_timezone_set(CObjRef object, CObjRef timezone) { object.getTyped<c_DateTime>()->t_settimezone(timezone); } Object f_date_sub(CObjRef datetime, CObjRef interval) { return datetime.getTyped<c_DateTime>()-> t_sub(interval.getTyped<c_DateInterval>()); } /////////////////////////////////////////////////////////////////////////////// // sun Array f_date_sun_info(int64_t ts, double latitude, double longitude) { return DateTime(ts, false).getSunInfo(latitude, longitude); } Variant f_date_sunrise(int64_t timestamp, int format /* = 0 */, double latitude /* = 0.0 */, double longitude /* = 0.0 */, double zenith /* = 0.0 */, double gmt_offset /* = 99999.0 */) { return DateTime(timestamp, false).getSunInfo (static_cast<DateTime::SunInfoFormat>(format), latitude, longitude, zenith, gmt_offset, false); } Variant f_date_sunset(int64_t timestamp, int format /* = 0 */, double latitude /* = 0.0 */, double longitude /* = 0.0 */, double zenith /* = 0.0 */, double gmt_offset /* = 99999.0 */) { return DateTime(timestamp, false).getSunInfo (static_cast<DateTime::SunInfoFormat>(format), latitude, longitude, zenith, gmt_offset, true); } /////////////////////////////////////////////////////////////////////////////// }
namespace HPHP { IMPLEMENT_DEFAULT_EXTENSION(date); /////////////////////////////////////////////////////////////////////////////// // constants const StaticString q_datetime_ATOM(LITSTR_INIT("Y-m-d\\TH:i:sP")); const StaticString q_datetime_COOKIE(LITSTR_INIT("l, d-M-y H:i:s T")); const StaticString q_datetime_ISO8601(LITSTR_INIT("Y-m-d\\TH:i:sO")); const StaticString q_datetime_RFC822(LITSTR_INIT("D, d M y H:i:s O")); const StaticString q_datetime_RFC850(LITSTR_INIT("l, d-M-y H:i:s T")); const StaticString q_datetime_RFC1036(LITSTR_INIT("D, d M y H:i:s O")); const StaticString q_datetime_RFC1123(LITSTR_INIT("D, d M Y H:i:s O")); const StaticString q_datetime_RFC2822(LITSTR_INIT("D, d M Y H:i:s O")); const StaticString q_datetime_RFC3339(LITSTR_INIT("Y-m-d\\TH:i:sP")); const StaticString q_datetime_RSS(LITSTR_INIT("D, d M Y H:i:s O")); const StaticString q_datetime_W3C(LITSTR_INIT("Y-m-d\\TH:i:sP")); const int64 q_datetimezone_AFRICA = 1; const int64 q_datetimezone_AMERICA = 2; const int64 q_datetimezone_ANTARCTICA = 4; const int64 q_datetimezone_ARCTIC = 8; const int64 q_datetimezone_ASIA = 16; const int64 q_datetimezone_ATLANTIC = 32; const int64 q_datetimezone_AUSTRALIA = 64; const int64 q_datetimezone_EUROPE = 128; const int64 q_datetimezone_INDIAN = 256; const int64 q_datetimezone_PACIFIC = 512; const int64 q_datetimezone_UTC = 1024; const int64 q_datetimezone_ALL = 2047; const int64 q_datetimezone_ALL_WITH_BC = 4095; const int64 q_datetimezone_PER_COUNTRY = 4096; /////////////////////////////////////////////////////////////////////////////// // methods c_datetime::c_datetime() { } c_datetime::~c_datetime() { } void c_datetime::t___construct(CStrRef time /*= "now"*/, CObjRef timezone /*= null_object*/) { m_dt = NEW(DateTime)(TimeStamp::Current()); if (!time.empty()) { m_dt->fromString(time, c_datetimezone::unwrap(timezone)); } } String c_datetime::t_format(CStrRef format) { return m_dt->toString(format, false); } int64 c_datetime::t_getoffset() { return m_dt->offset(); } Variant c_datetime::t_gettimezone() { SmartObject<TimeZone> tz = m_dt->timezone(); if (tz->isValid()) { return c_datetimezone::wrap(tz); } return false; } Object c_datetime::t_modify(CStrRef modify) { m_dt->modify(modify); return this; } Object c_datetime::t_setdate(int64 year, int64 month, int64 day) { m_dt->setDate(year, month, day); return this; } Object c_datetime::t_setisodate(int64 year, int64 week, int64 day /*= 1*/) { m_dt->setISODate(year, week, day); return this; } Object c_datetime::t_settime(int64 hour, int64 minute, int64 second /*= 0*/) { m_dt->setTime(hour, minute, second); return this; } Object c_datetime::t_settimezone(CObjRef timezone) { m_dt->setTimezone(c_datetimezone::unwrap(timezone)); return this; } Variant c_datetime::t___destruct() { return null; } c_datetimezone::c_datetimezone() { } c_datetimezone::~c_datetimezone() { } void c_datetimezone::t___construct(CStrRef timezone) { m_tz = NEW(TimeZone)(timezone); } String c_datetimezone::t_getname() { return m_tz->name(); } int64 c_datetimezone::t_getoffset(CObjRef datetime) { bool error; int64 ts = c_datetime::unwrap(datetime)->toTimeStamp(error); return m_tz->offset(ts); } Array c_datetimezone::t_gettransitions() { return m_tz->transitions(); } Array c_datetimezone::ti_listabbreviations(const char* cls) { return TimeZone::GetAbbreviations(); } Array c_datetimezone::ti_listidentifiers(const char* cls) { return TimeZone::GetNames(); } Variant c_datetimezone::t___destruct() { return null; } /////////////////////////////////////////////////////////////////////////////// }
namespace VM { /////////////////////////////////////////////////////////////////////////////// static StaticString s_stdclass(LITSTR_INIT("stdclass")); static StaticString s_Exception(LITSTR_INIT("Exception")); static StaticString s_BadMethodCallException( LITSTR_INIT("BadMethodCallException")); static StaticString s_Directory(LITSTR_INIT("Directory")); static StaticString s_RecursiveDirectoryIterator( LITSTR_INIT("RecursiveDirectoryIterator")); static StaticString s_SplFileInfo(LITSTR_INIT("SplFileInfo")); static StaticString s_SplFileObject(LITSTR_INIT("SplFileObject")); static StaticString s_pinitSentinel(LITSTR_INIT("__pinitSentinel")); static StaticString s_resource(LITSTR_INIT("__resource")); static StaticString s_DOMException(LITSTR_INIT("DOMException")); static StaticString s_PDOException(LITSTR_INIT("PDOException")); static StaticString s_SoapFault(LITSTR_INIT("SoapFault")); class VMClassInfoHook : public ClassInfoHook { public: virtual Array getUserFunctions() const { return g_vmContext->getUserFunctionsInfo(); } virtual Array getClasses() const { return Unit::getClassesInfo(); } virtual Array getInterfaces() const { return Unit::getInterfacesInfo(); } virtual Array getTraits() const { return Unit::getTraitsInfo(); } virtual Array getConstants() const { return g_vmContext->getConstantsInfo(); } virtual const ClassInfo::MethodInfo *findFunction(CStrRef name) const { return g_vmContext->findFunctionInfo(name); } virtual const ClassInfo *findClassLike(CStrRef name) const { const ClassInfo* ci; if ((ci = g_vmContext->findClassInfo(name)) != NULL || (ci = g_vmContext->findInterfaceInfo(name)) != NULL || (ci = g_vmContext->findTraitInfo(name)) != NULL) { return ci; } return NULL; } virtual const ClassInfo *findInterface(CStrRef name) const { return g_vmContext->findInterfaceInfo(name); } virtual const ClassInfo* findTrait(CStrRef name) const { return g_vmContext->findTraitInfo(name); } virtual const ClassInfo::ConstantInfo *findConstant(CStrRef name) const { return g_vmContext->findConstantInfo(name); } }; static VMClassInfoHook vm_class_info_hook; void ProcessInit() { // Initialize compiler state VM::compile_file(0, 0, MD5(), 0); // Install VM's ClassInfoHook ClassInfo::SetHook(&vm_class_info_hook); VM::Transl::Translator::Get()->processInit(); Transl::TargetCache::requestInit(); Unit* nativeFuncUnit = build_native_func_unit(hhbc_ext_funcs, hhbc_ext_funcs_count); SystemLib::s_nativeFuncUnit = nativeFuncUnit; // Search for systemlib.php in the following places: // 1) ${HHVM_LIB_PATH}/systemlib.php // 2) <dirname(realpath(hhvm))>/systemlib.php (requires proc filesystem) // 3) ${HPHP_LIB}/systemlib.php // 4) <HHVM_LIB_PATH_DEFAULT>/systemlib.php // // HHVM_LIB_PATH allows a manual override at runtime. If systemlib.php // exists next to the hhvm binary, that is likely to be the next best // version to use. The realpath()-based lookup will succeed as long as the // proc filesystem exists (e.g. on Linux and some FreeBSD configurations) // and no hard links are in use for the executable. Under certain build // situations, systemlib.php will not be generated next to hhvm binary, so // ${HPHP_LIB} is checked next. Failing all of those options, the // HHVM_LIB_PATH_DEFAULT-based lookup will always succeed, assuming that the // application was built and installed correctly. String currentDir = g_vmContext->getCwd(); HPHP::Eval::PhpFile* file = NULL; #define SYSTEMLIB_PHP "/systemlib.php" #define LOOKUP_STR(s) do { \ String systemlibPath = String(s) + SYSTEMLIB_PHP; \ file = g_vmContext->lookupPhpFile(systemlibPath.get(), currentDir.data(), \ NULL); \ } while (0) #define LOOKUP_ENV(v) do { \ if (!file) { \ const char* s = getenv(#v); \ if (s && *s) { \ LOOKUP_STR(s); \ } \ } \ } while (0) #define LOOKUP_CPP(v) do { \ if (!file) { \ LOOKUP_STR(v); \ } \ } while (0) LOOKUP_ENV(HHVM_LIB_PATH); if (!file) { char hhvm_exe[PATH_MAX+1]; char hhvm_path[PATH_MAX+1]; ssize_t len = readlink("/proc/self/exe", hhvm_exe, sizeof(hhvm_exe)); if (len >= 0) { hhvm_exe[len] = '\0'; if (realpath(hhvm_exe, hhvm_path) != NULL) { char *hphp_lib = dirname(hhvm_path); LOOKUP_STR(hphp_lib); } } } LOOKUP_ENV(HPHP_LIB); #ifdef HHVM_LIB_PATH_DEFAULT LOOKUP_CPP(HHVM_LIB_PATH_DEFAULT); #endif if (!file) { // Die a horrible death. Logger::Error("Unable to find/load systemlib.php"); _exit(1); } #undef SYSTEMLIB_PHP #undef LOOKUP_STR #undef LOOKUP_ENV #undef LOOKUP_CPP SystemLib::s_phpFile = file; file->incRef(); SystemLib::s_unit = file->unit(); // Load the systemlib unit to build the Class objects SystemLib::s_unit->merge(); // load builtins SystemLib::s_nativeFuncUnit->merge(); #define INIT_SYSTEMLIB_CLASS_FIELD(cls) \ { \ Class *cls = *Unit::GetNamedEntity(s_##cls.get())->clsList(); \ ASSERT(cls); \ SystemLib::s_##cls##Class = cls; \ } // Stash a pointer to the VM Classes for stdclass, Exception, // pinitSentinel and resource INIT_SYSTEMLIB_CLASS_FIELD(stdclass); INIT_SYSTEMLIB_CLASS_FIELD(Exception); INIT_SYSTEMLIB_CLASS_FIELD(BadMethodCallException); INIT_SYSTEMLIB_CLASS_FIELD(Directory); INIT_SYSTEMLIB_CLASS_FIELD(RecursiveDirectoryIterator); INIT_SYSTEMLIB_CLASS_FIELD(SplFileInfo); INIT_SYSTEMLIB_CLASS_FIELD(SplFileObject); INIT_SYSTEMLIB_CLASS_FIELD(pinitSentinel); INIT_SYSTEMLIB_CLASS_FIELD(resource); INIT_SYSTEMLIB_CLASS_FIELD(DOMException); INIT_SYSTEMLIB_CLASS_FIELD(PDOException); INIT_SYSTEMLIB_CLASS_FIELD(SoapFault); #undef INIT_SYSTEMLIB_CLASS_FIELD // We call a special bytecode emitter function to build the native // unit which will contain all of our cppext functions and classes. // Each function and method will have a bytecode body that will thunk // to the native implementation. Unit* nativeClassUnit = build_native_class_unit(hhbc_ext_classes, hhbc_ext_class_count); SystemLib::s_nativeClassUnit = nativeClassUnit; // Load the nativelib unit to build the Class objects SystemLib::s_nativeClassUnit->merge(); // Retrieve all of the class pointers for (long long i = 0LL; i < hhbc_ext_class_count; ++i) { const HhbcExtClassInfo* info = hhbc_ext_classes + i; const StringData* name = StringData::GetStaticString(info->m_name); const NamedEntity* ne = Unit::GetNamedEntity(name); Class* cls = Unit::lookupClass(ne); ASSERT(cls); const ObjectStaticCallbacks* osc = get_object_static_callbacks(info->m_name); ASSERT(osc != NULL); *(osc->os_cls_ptr) = cls; } Stack::ValidateStackSize(); SystemLib::s_inited = true; // For debug build, run some quick unit tests at process start time if (debug) { VM::Transl::FixupMapUnitTest _; } } /////////////////////////////////////////////////////////////////////////////// }
namespace HPHP { /////////////////////////////////////////////////////////////////////////////// String DebuggerThriftBuffer::readImpl() { assert(m_size <= BUFFER_SIZE); int nread = m_socket->readImpl(m_buffer, m_size); m_buffer[nread] = '\0'; return String(m_buffer, nread, AttachLiteral); } void DebuggerThriftBuffer::flushImpl(CStrRef data) { m_socket->write(data); } void DebuggerThriftBuffer::throwError(const char *msg, int code) { throw Exception("Protocol Error (%d): %s", code, msg); } /////////////////////////////////////////////////////////////////////////////// static StaticString s_hit_limit(LITSTR_INIT("Hit serialization limit")); static StaticString s_unknown_exp(LITSTR_INIT("Hit unknown exception")); static StaticString s_type_mismatch(LITSTR_INIT("Type mismatch")); template<typename T> static inline int serializeImpl(T data, String& sdata) { VariableSerializer vs(VariableSerializer::DebuggerSerialize); try { sdata = vs.serialize(data, true); } catch (StringBufferLimitException &e) { sdata = s_hit_limit; return DebuggerWireHelpers::HitLimit; } catch (...) { sdata = s_unknown_exp; return DebuggerWireHelpers::UnknownError; } return DebuggerWireHelpers::NoError; } static inline int unserializeImpl(CStrRef sdata, Variant& data) { if (sdata.same(s_hit_limit)) { return DebuggerWireHelpers::HitLimit; } if (sdata.same(s_unknown_exp)) { return DebuggerWireHelpers::UnknownError; } VariableUnserializer vu(sdata.data(), sdata.size(), VariableUnserializer::Serialize, true); try { data = vu.unserialize(); } catch (Exception &e) { data = null_variant; return DebuggerWireHelpers::UnknownError; } return DebuggerWireHelpers::NoError; } int DebuggerWireHelpers::WireSerialize(CArrRef data, String& sdata) { return serializeImpl(data, sdata); } int DebuggerWireHelpers::WireSerialize(CObjRef data, String& sdata) { return serializeImpl(data, sdata); } int DebuggerWireHelpers::WireSerialize(CVarRef data, String& sdata) { return serializeImpl(data, sdata); } int DebuggerWireHelpers::WireUnserialize(String& sdata, Array& data) { Variant v; int ret = unserializeImpl(sdata, v); if (ret != NoError) { return ret; } if (!v.isArray() && !v.isNull()) { sdata = s_type_mismatch; return TypeMismatch; } data = v; return NoError; } int DebuggerWireHelpers::WireUnserialize(String& sdata, Object& data) { Variant v; int ret = unserializeImpl(sdata, v); if (ret != NoError) { return ret; } if (!v.isObject() && !v.isNull()) { sdata = s_type_mismatch; return TypeMismatch; } data = v; return NoError; } int DebuggerWireHelpers::WireUnserialize(String& sdata, Variant& data) { return unserializeImpl(sdata, data); } /////////////////////////////////////////////////////////////////////////////// }
namespace HPHP { IMPLEMENT_DEFAULT_EXTENSION(date); /////////////////////////////////////////////////////////////////////////////// // constants const StaticString q_DateTime$$ATOM(LITSTR_INIT("Y-m-d\\TH:i:sP")); const StaticString q_DateTime$$COOKIE(LITSTR_INIT("l, d-M-y H:i:s T")); const StaticString q_DateTime$$ISO8601(LITSTR_INIT("Y-m-d\\TH:i:sO")); const StaticString q_DateTime$$RFC822(LITSTR_INIT("D, d M y H:i:s O")); const StaticString q_DateTime$$RFC850(LITSTR_INIT("l, d-M-y H:i:s T")); const StaticString q_DateTime$$RFC1036(LITSTR_INIT("D, d M y H:i:s O")); const StaticString q_DateTime$$RFC1123(LITSTR_INIT("D, d M Y H:i:s O")); const StaticString q_DateTime$$RFC2822(LITSTR_INIT("D, d M Y H:i:s O")); const StaticString q_DateTime$$RFC3339(LITSTR_INIT("Y-m-d\\TH:i:sP")); const StaticString q_DateTime$$RSS(LITSTR_INIT("D, d M Y H:i:s O")); const StaticString q_DateTime$$W3C(LITSTR_INIT("Y-m-d\\TH:i:sP")); const int64 q_DateTimeZone$$AFRICA = 1; const int64 q_DateTimeZone$$AMERICA = 2; const int64 q_DateTimeZone$$ANTARCTICA = 4; const int64 q_DateTimeZone$$ARCTIC = 8; const int64 q_DateTimeZone$$ASIA = 16; const int64 q_DateTimeZone$$ATLANTIC = 32; const int64 q_DateTimeZone$$AUSTRALIA = 64; const int64 q_DateTimeZone$$EUROPE = 128; const int64 q_DateTimeZone$$INDIAN = 256; const int64 q_DateTimeZone$$PACIFIC = 512; const int64 q_DateTimeZone$$UTC = 1024; const int64 q_DateTimeZone$$ALL = 2047; const int64 q_DateTimeZone$$ALL_WITH_BC = 4095; const int64 q_DateTimeZone$$PER_COUNTRY = 4096; /////////////////////////////////////////////////////////////////////////////// // methods c_DateTime::c_DateTime(const ObjectStaticCallbacks *cb) : ExtObjectData(cb) { CPP_BUILTIN_CLASS_INIT(DateTime); } c_DateTime::~c_DateTime() { } void c_DateTime::t___construct(CStrRef time /*= "now"*/, CObjRef timezone /*= null_object*/) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::__construct); m_dt = NEWOBJ(DateTime)(TimeStamp::Current()); if (!time.empty()) { m_dt->fromString(time, c_DateTimeZone::unwrap(timezone)); } } String c_DateTime::t_format(CStrRef format) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::format); return m_dt->toString(format, false); } int64 c_DateTime::t_getoffset() { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::getoffset); return m_dt->offset(); } Variant c_DateTime::t_gettimezone() { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::gettimezone); SmartObject<TimeZone> tz = m_dt->timezone(); if (tz->isValid()) { return c_DateTimeZone::wrap(tz); } return false; } Object c_DateTime::t_modify(CStrRef modify) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::modify); m_dt->modify(modify); return this; } Object c_DateTime::t_setdate(int64 year, int64 month, int64 day) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::setdate); m_dt->setDate(year, month, day); return this; } Object c_DateTime::t_setisodate(int64 year, int64 week, int64 day /*= 1*/) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::setisodate); m_dt->setISODate(year, week, day); return this; } Object c_DateTime::t_settime(int64 hour, int64 minute, int64 second /*= 0*/) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::settime); m_dt->setTime(hour, minute, second); return this; } Object c_DateTime::t_settimezone(CObjRef timezone) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::settimezone); m_dt->setTimezone(c_DateTimeZone::unwrap(timezone)); return this; } Variant c_DateTime::t___destruct() { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::__destruct); return null; } ObjectData *c_DateTime::clone() { ObjectData *obj = ObjectData::clone(); c_DateTime *dt = static_cast<c_DateTime*>(obj); dt->m_dt = m_dt->cloneDateTime(); return obj; } c_DateTimeZone::c_DateTimeZone(const ObjectStaticCallbacks *cb) : ExtObjectData(cb) { CPP_BUILTIN_CLASS_INIT(DateTimeZone); } c_DateTimeZone::~c_DateTimeZone() { } void c_DateTimeZone::t___construct(CStrRef timezone) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::__construct); m_tz = NEWOBJ(TimeZone)(timezone); if (!m_tz->isValid()) { std::string msg = "DateTimeZone::__construct(): Unknown or bad timezone ("; msg += timezone.data(); msg += ")"; throw Object(SystemLib::AllocExceptionObject(msg)); } } String c_DateTimeZone::t_getname() { INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::getname); return m_tz->name(); } int64 c_DateTimeZone::t_getoffset(CObjRef datetime) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::getoffset); bool error; int64 ts = c_DateTime::unwrap(datetime)->toTimeStamp(error); return m_tz->offset(ts); } Array c_DateTimeZone::t_gettransitions() { INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::gettransitions); return m_tz->transitions(); } Array c_DateTimeZone::ti_listabbreviations(const char* cls) { STATIC_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::listabbreviations); return TimeZone::GetAbbreviations(); } Array c_DateTimeZone::ti_listidentifiers(const char* cls) { STATIC_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::listidentifiers); return TimeZone::GetNames(); } Variant c_DateTimeZone::t___destruct() { INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::__destruct); return null; } ObjectData *c_DateTimeZone::clone() { ObjectData *obj = ObjectData::clone(); c_DateTimeZone *dtz = static_cast<c_DateTimeZone*>(obj); dtz->m_tz = m_tz->cloneTimeZone(); return obj; } /////////////////////////////////////////////////////////////////////////////// }
namespace HPHP { struct DateGlobals { double default_latitude; double default_longitude; double sunset_zenith; double sunrise_zenith; }; IMPLEMENT_THREAD_LOCAL(DateGlobals, s_date_globals); static class DateExtension : public Extension { public: DateExtension() : Extension("date", k_PHP_VERSION.c_str()) { } void threadInit() { IniSetting::Bind( this, IniSetting::PHP_INI_ALL, "date.timezone", g_context->getDefaultTimeZone().c_str(), IniSetting::SetAndGet<std::string>( dateTimezoneIniUpdate, dateTimezoneIniGet ) ); IniSetting::Bind( this, IniSetting::PHP_INI_ALL, "date.default_latitude", "31.7667", &s_date_globals->default_latitude ); IniSetting::Bind( this, IniSetting::PHP_INI_ALL, "date.default_longitude", "35.2333", &s_date_globals->default_longitude ); IniSetting::Bind( this, IniSetting::PHP_INI_ALL, "date.sunset_zenith", "90.583333", &s_date_globals->sunset_zenith ); IniSetting::Bind( this, IniSetting::PHP_INI_ALL, "date.sunrise_zenith", "90.583333", &s_date_globals->sunrise_zenith ); } double get_date_default_gmt_offset() { SmartResource<TimeZone> tzi = TimeZone::Current(); // just get the offset form utc time // set the timestamp 0 is ok return tzi->offset(0) / 3600; } private: static bool dateTimezoneIniUpdate(const std::string& value) { if (value.empty()) { return false; } return f_date_default_timezone_set(value); } static std::string dateTimezoneIniGet() { auto ret = g_context->getTimeZone(); if (ret.isNull()) { return ""; } return ret.toCppString(); } } s_date_extension; /////////////////////////////////////////////////////////////////////////////// // constants const StaticString q_DateTime$$ATOM(LITSTR_INIT("Y-m-d\\TH:i:sP")); const StaticString q_DateTime$$COOKIE(LITSTR_INIT("l, d-M-y H:i:s T")); const StaticString q_DateTime$$ISO8601(LITSTR_INIT("Y-m-d\\TH:i:sO")); const StaticString q_DateTime$$RFC822(LITSTR_INIT("D, d M y H:i:s O")); const StaticString q_DateTime$$RFC850(LITSTR_INIT("l, d-M-y H:i:s T")); const StaticString q_DateTime$$RFC1036(LITSTR_INIT("D, d M y H:i:s O")); const StaticString q_DateTime$$RFC1123(LITSTR_INIT("D, d M Y H:i:s O")); const StaticString q_DateTime$$RFC2822(LITSTR_INIT("D, d M Y H:i:s O")); const StaticString q_DateTime$$RFC3339(LITSTR_INIT("Y-m-d\\TH:i:sP")); const StaticString q_DateTime$$RSS(LITSTR_INIT("D, d M Y H:i:s O")); const StaticString q_DateTime$$W3C(LITSTR_INIT("Y-m-d\\TH:i:sP")); const int64_t q_DateTimeZone$$AFRICA = 1; const int64_t q_DateTimeZone$$AMERICA = 2; const int64_t q_DateTimeZone$$ANTARCTICA = 4; const int64_t q_DateTimeZone$$ARCTIC = 8; const int64_t q_DateTimeZone$$ASIA = 16; const int64_t q_DateTimeZone$$ATLANTIC = 32; const int64_t q_DateTimeZone$$AUSTRALIA = 64; const int64_t q_DateTimeZone$$EUROPE = 128; const int64_t q_DateTimeZone$$INDIAN = 256; const int64_t q_DateTimeZone$$PACIFIC = 512; const int64_t q_DateTimeZone$$UTC = 1024; const int64_t q_DateTimeZone$$ALL = 2047; const int64_t q_DateTimeZone$$ALL_WITH_BC = 4095; const int64_t q_DateTimeZone$$PER_COUNTRY = 4096; /////////////////////////////////////////////////////////////////////////////// // methods Object c_DateTime::t_add(const Object& interval) { m_dt->add(c_DateInterval::unwrap(interval)); return this; } void c_DateTime::t___construct(const String& time /*= "now"*/, const Object& timezone /*= null_object*/) { m_dt = NEWOBJ(DateTime)(TimeStamp::Current()); if (!time.empty()) { m_dt->fromString(time, c_DateTimeZone::unwrap(timezone)); } else if (!timezone.isNull()) { // We still have to tell the underlying DateTime the timezone incase they // call setTimestamp or something else later m_dt->setTimezone(c_DateTimeZone::unwrap(timezone)); } } Variant c_DateTime::ti_createfromformat(const String& format, const String& time, const Object& timezone /*= null_object */) { c_DateTime *datetime = NEWOBJ(c_DateTime); const auto curr = (format.find("!") != String::npos) ? 0 : f_time() ; datetime->m_dt = NEWOBJ(DateTime(curr, false)); if (!datetime->m_dt->fromString(time, c_DateTimeZone::unwrap(timezone), format.data(), false)) { return false; } return datetime; } Object c_DateTime::t_diff(const Object& datetime2, bool absolute) { return c_DateInterval::wrap(m_dt->diff(c_DateTime::unwrap(datetime2), absolute)); } String c_DateTime::t_format(const String& format) { return m_dt->toString(format, false); } const StaticString s_data("data"); const StaticString s_getTimestamp("getTimestamp"); int64_t c_DateTime::GetTimestamp(const Object& obj) { if (LIKELY(obj.is<c_DateTime>())) { return obj.getTyped<c_DateTime>(true)->t_gettimestamp(); } assert(obj->instanceof(SystemLib::s_DateTimeInterfaceClass)); Variant result = obj->o_invoke(s_getTimestamp, Array::Create()); return result.toInt64(); } int64_t c_DateTime::GetTimestamp(const ObjectData* od) { return GetTimestamp(Object(const_cast<ObjectData*>(od))); } SmartResource<DateTime> c_DateTime::unwrap(const Object& datetime) { if (LIKELY(datetime.is<c_DateTime>())) { SmartObject<c_DateTime> cdt = datetime.getTyped<c_DateTime>(true); if (cdt.get() == nullptr) return SmartResource<DateTime>(); return cdt->m_dt; } if (datetime->instanceof(SystemLib::s_DateTimeImmutableClass)) { bool visible, accessible, unset; TypedValue* tv = datetime->getProp(SystemLib::s_DateTimeImmutableClass, s_data.get(), visible, accessible, unset); assert(tv->m_type == KindOfObject); Object impl(tv->m_data.pobj); return unwrap(impl); } return SmartResource<DateTime>(); } const StaticString s_warning_count("warning_count"), s_warnings("warnings"), s_error_count("error_count"), s_errors("errors"); Array c_DateTime::ti_getlasterrors() { Array errors = DateTime::getLastErrors(); Array warnings = DateTime::getLastWarnings(); Array ret = Array::Create(); ret.add(s_warning_count, warnings.size()); ret.add(s_warnings, warnings); ret.add(s_error_count, errors.size()); ret.add(s_errors, errors); return ret; } int64_t c_DateTime::t_getoffset() { return m_dt->offset(); } int64_t c_DateTime::t_gettimestamp() { return gettimestamp(); } int64_t c_DateTime::gettimestamp() const { bool err = false; return m_dt->toTimeStamp(err); } Variant c_DateTime::t_gettimezone() { SmartResource<TimeZone> tz = m_dt->timezone(); if (tz->isValid()) { return c_DateTimeZone::wrap(tz); } return false; } Object c_DateTime::t_modify(const String& modify) { m_dt->modify(modify); return this; } Object c_DateTime::t_setdate(int64_t year, int64_t month, int64_t day) { m_dt->setDate(year, month, day); return this; } Object c_DateTime::t_setisodate(int64_t year, int64_t week, int64_t day /*= 1*/) { m_dt->setISODate(year, week, day); return this; } Object c_DateTime::t_settime(int64_t hour, int64_t minute, int64_t second /*= 0*/) { m_dt->setTime(hour, minute, second); return this; } Object c_DateTime::t_settimestamp(int64_t unixtimestamp) { m_dt->fromTimeStamp(unixtimestamp, false); return this; } Object c_DateTime::t_settimezone(const Object& timezone) { m_dt->setTimezone(c_DateTimeZone::unwrap(timezone)); return this; } Object c_DateTime::t_sub(const Object& interval) { m_dt->sub(c_DateInterval::unwrap(interval)); return this; } const StaticString s_c("c"), s__date_time("_date_time"); Array c_DateTime::t___sleep() { o_set(s__date_time, t_format(s_c)); return make_packed_array(s__date_time); } void c_DateTime::t___wakeup() { t___construct(o_get(s__date_time)); unsetProp(getVMClass(), s__date_time.get()); } const StaticString s_date("date"), s_timezone_type("timezone_type"), s_timezone("timezone"), s_ISOformat("Y-m-d H:i:s"); Array c_DateTime::t___debuginfo() { ArrayInit ret(3); ret.set(s_date, t_format(s_ISOformat)); ret.set(s_timezone_type, m_dt->zoneType()); ret.set(s_timezone, m_dt->timezone()->name()); return ret.create(); } c_DateTime* c_DateTime::Clone(ObjectData* obj) { c_DateTime* dt = static_cast<c_DateTime*>(obj->cloneImpl()); dt->m_dt = static_cast<c_DateTime*>(obj)->m_dt->cloneDateTime(); return dt; } void c_DateTimeZone::t___construct(const String& timezone) { m_tz = NEWOBJ(TimeZone)(timezone); if (!m_tz->isValid()) { std::string msg = "DateTimeZone::__construct(): Unknown or bad timezone ("; msg += timezone.data(); msg += ")"; throw Object(SystemLib::AllocExceptionObject(msg)); } } Array c_DateTimeZone::t_getlocation() { return m_tz->getLocation(); } String c_DateTimeZone::t_getname() { return m_tz->name(); } int64_t c_DateTimeZone::t_getoffset(const Object& datetime) { bool error; int64_t ts = c_DateTime::unwrap(datetime)->toTimeStamp(error); return m_tz->offset(ts); } Array c_DateTimeZone::t_gettransitions() { return m_tz->transitions(); } Array c_DateTimeZone::ti_listabbreviations() { return TimeZone::GetAbbreviations(); } Array c_DateTimeZone::ti_listidentifiers() { return TimeZone::GetNames(); } c_DateTimeZone* c_DateTimeZone::Clone(ObjectData* obj) { c_DateTimeZone* dtz = static_cast<c_DateTimeZone*>(obj->cloneImpl()); dtz->m_tz = static_cast<c_DateTimeZone*>(obj)->m_tz->cloneTimeZone(); return dtz; } void c_DateInterval::t___construct(const String& interval_spec) { m_di = NEWOBJ(DateInterval)(interval_spec); if (!m_di->isValid()) { std::string msg = "DateInterval::__construct: Invalid interval ("; msg += interval_spec.data(); msg += ")"; throw Object(SystemLib::AllocExceptionObject(msg)); } } const StaticString s_y("y"), s_m("m"), s_d("d"), s_h("h"), s_i("i"), s_s("s"), s_invert("invert"), s_days("days"); Variant c_DateInterval::t___get(Variant member) { if (member.isString()) { if (same(member, s_y)) return m_di->getYears(); if (same(member, s_m)) return m_di->getMonths(); if (same(member, s_d)) return m_di->getDays(); if (same(member, s_h)) return m_di->getHours(); if (same(member, s_i)) return m_di->getMinutes(); if (same(member, s_s)) return m_di->getSeconds(); if (same(member, s_invert)) return m_di->isInverted(); if (same(member, s_days)) { if (m_di->haveTotalDays()) { return m_di->getTotalDays(); } else { return false; } } } std::string msg = "Undefined property '"; msg += member.toString().data(); msg += ") on DateInterval object"; throw Object(SystemLib::AllocExceptionObject(msg)); } Variant c_DateInterval::t___set(Variant member, Variant value) { if (member.isString()) { if (same(member, s_y)) { m_di->setYears(value.toInt64()); return uninit_null(); } if (same(member, s_m)) { m_di->setMonths(value.toInt64()); return uninit_null(); } if (same(member, s_d)) { m_di->setDays(value.toInt64()); return uninit_null(); } if (same(member, s_h)) { m_di->setHours(value.toInt64()); return uninit_null(); } if (same(member, s_i)) { m_di->setMinutes(value.toInt64()); return uninit_null(); } if (same(member, s_s)) { m_di->setSeconds(value.toInt64()); return uninit_null(); } if (same(member, s_invert)) { m_di->setInverted(value.toBoolean()); return uninit_null(); } if (same(member, s_days)) { m_di->setTotalDays(value.toInt64()); return uninit_null(); } } std::string msg = "Undefined property '"; msg += member.toString().data(); msg += ") on DateInterval object"; throw Object(SystemLib::AllocExceptionObject(msg)); } Object c_DateInterval::ti_createfromdatestring(const String& time) { SmartResource<DateInterval> di(NEWOBJ(DateInterval)(time, true)); return c_DateInterval::wrap(di); } String c_DateInterval::t_format(const String& format) { return m_di->format(format); } c_DateInterval* c_DateInterval::Clone(ObjectData* obj) { c_DateInterval *di = static_cast<c_DateInterval*>(obj->cloneImpl()); di->m_di = static_cast<c_DateInterval*>(obj)->m_di->cloneDateInterval(); return di; } /////////////////////////////////////////////////////////////////////////////// // timestamp Variant f_gettimeofday(bool return_float /* = false */) { if (return_float) { return TimeStamp::CurrentSecond(); } return TimeStamp::CurrentTime(); } Variant f_microtime(bool get_as_float /* = false */) { if (get_as_float) { return TimeStamp::CurrentSecond(); } return TimeStamp::CurrentMicroTime(); } int64_t f_time() { return time(0); } Variant f_mktime(int hour /* = INT_MAX */, int minute /* = INT_MAX */, int second /* = INT_MAX */, int month /* = INT_MAX */, int day /* = INT_MAX */, int year /* = INT_MAX */) { bool error; int64_t ts = TimeStamp::Get(error, hour, minute, second, month, day, year, false); if (error) return false; return ts; } Variant f_gmmktime(int hour /* = INT_MAX */, int minute /* = INT_MAX */, int second /* = INT_MAX */, int month /* = INT_MAX */, int day /* = INT_MAX */, int year /* = INT_MAX */) { bool error; int64_t ts = TimeStamp::Get(error, hour, minute, second, month, day, year, true); if (error) return false; return ts; } Variant f_idate(const String& format, int64_t timestamp /* = TimeStamp::Current() */) { if (format.size() != 1) { throw_invalid_argument("format: %s", format.data()); return false; } int64_t ret = DateTime(timestamp, false).toInteger(*format.data()); if (ret == -1) return false; return ret; } Variant f_date(const String& format, int64_t timestamp /* = TimeStamp::Current() */) { if (format.empty()) return ""; String ret = DateTime(timestamp, false).toString(format, false); if (ret.isNull()) return false; return ret; } Variant f_gmdate(const String& format, int64_t timestamp /* = TimeStamp::Current() */) { String ret = DateTime(timestamp, true).toString(format, false); if (ret.isNull()) return false; return ret; } Variant f_strftime(const String& format, int64_t timestamp /* = TimeStamp::Current() */) { String ret = DateTime(timestamp, false).toString(format, true); if (ret.isNull()) return false; return ret; } String f_gmstrftime(const String& format, int64_t timestamp /* = TimeStamp::Current() */) { String ret = DateTime(timestamp, true).toString(format, true); if (ret.isNull()) return false; return ret; } Array f_getdate(int64_t timestamp /* = TimeStamp::Current() */) { return DateTime(timestamp, false).toArray(DateTime::ArrayFormat::TimeMap); } Array f_localtime(int64_t timestamp /* = TimeStamp::Current() */, bool is_associative /* = false */) { DateTime::ArrayFormat format = is_associative ? DateTime::ArrayFormat::TmMap : DateTime::ArrayFormat::TmVector; return DateTime(timestamp, false).toArray(format); } Variant f_strptime(const String& date, const String& format) { Array ret = DateTime::ParseAsStrptime(format, date); if (ret.empty()) { return false; } return ret; } Variant f_strtotime(const String& input, int64_t timestamp /* = TimeStamp::Current() */) { if (input.empty()) { return false; } DateTime dt(timestamp); if (!dt.fromString(input, SmartResource<TimeZone>(), nullptr, false)) { return false; } bool error; return dt.toTimeStamp(error); } /////////////////////////////////////////////////////////////////////////////// // timezone String f_date_default_timezone_get() { return TimeZone::Current()->name(); } bool f_date_default_timezone_set(const String& name) { return TimeZone::SetCurrent(name); } Array f_timezone_identifiers_list() { return c_DateTimeZone::ti_listidentifiers(); } Array f_timezone_abbreviations_list() { return c_DateTimeZone::ti_listabbreviations(); } Variant f_timezone_name_from_abbr(const String& abbr, int gmtoffset /* = -1 */, bool isdst /* = true */) { String ret = TimeZone::AbbreviationToName(abbr, gmtoffset, isdst); if (ret.isNull()) { return false; } return ret; } Object f_timezone_open(const String& timezone) { c_DateTimeZone *ctz = NEWOBJ(c_DateTimeZone)(); Object ret(ctz); ctz->t___construct(timezone); return ret; } Array f_timezone_location_get(const Object& timezone) { return timezone.getTyped<c_DateTimeZone>()->t_getlocation(); } String f_timezone_name_get(const Object& object) { return object.getTyped<c_DateTimeZone>()->t_getname(); } int64_t f_timezone_offset_get(const Object& object, const Object& dt) { return object.getTyped<c_DateTimeZone>()->t_getoffset(dt); } Array f_timezone_transitions_get(const Object& object) { return object.getTyped<c_DateTimeZone>()->t_gettransitions(); } String f_timezone_version_get() { return TimeZone::getVersion(); } /////////////////////////////////////////////////////////////////////////////// // datetime bool f_checkdate(int month, int day, int year) { return DateTime::IsValid(year, month, day); } Object f_date_add(const Object& datetime, const Object& interval) { return datetime.getTyped<c_DateTime>()-> t_add(interval.getTyped<c_DateInterval>()); } Variant f_date_create_from_format(const String& format, const String& time, const Object& timezone /* = null_object */) { return c_DateTime::ti_createfromformat(format, time, timezone); } Variant f_date_parse_from_format(const String& format, const String& date) { Array ret = DateTime::Parse(format, date); if (ret.empty()) { return false; } return ret; } Variant f_date_create(const String& time /* = null_string */, const Object& timezone /* = null_object */) { c_DateTime *cdt = NEWOBJ(c_DateTime)(); Object ret(cdt); // Don't set the time here because it will throw if it is bad cdt->t___construct(); if (time.empty()) { // zend does this, so so do we return ret; } auto dt = c_DateTime::unwrap(ret); if (!dt->fromString(time, c_DateTimeZone::unwrap(timezone), nullptr, false)) { return false; } return ret; } void f_date_date_set(const Object& object, int year, int month, int day) { object.getTyped<c_DateTime>()->t_setdate(year, month, day); } Object f_date_diff(const Object& datetime, const Object& datetime2, bool absolute /* = false */) { return datetime.getTyped<c_DateTime>()-> t_diff(datetime2.getTyped<c_DateTime>(), absolute); } void f_date_isodate_set(const Object& object, int year, int week, int day /* = 1 */) { object.getTyped<c_DateTime>()->t_setisodate(year, week, day); } String f_date_format(const Object& object, const String& format) { return object.getTyped<c_DateTime>()->t_format(format); } Array f_date_get_last_errors() { return c_DateTime::ti_getlasterrors(); } Object f_date_interval_create_from_date_string(const String& time) { return c_DateInterval::ti_createfromdatestring(time); } String f_date_interval_format(const Object& interval, const String& format_spec) { return interval.getTyped<c_DateInterval>()->t_format(format_spec); } void f_date_modify(const Object& object, const String& modify) { object.getTyped<c_DateTime>()->t_modify(modify); } Variant f_date_parse(const String& date) { Array ret = DateTime::Parse(date); if (ret.empty()) { return false; } return ret; } void f_date_time_set(const Object& object, int hour, int minute, int second /* = 0 */) { object.getTyped<c_DateTime>()->t_settime(hour, minute, second); } int64_t f_date_timestamp_get(const Object& datetime) { return datetime.getTyped<c_DateTime>()->t_gettimestamp(); } Object f_date_timestamp_set(const Object& datetime, int64_t timestamp) { return datetime.getTyped<c_DateTime>()-> t_settimestamp(timestamp); } Variant f_date_timezone_get(const Object& object) { return object.getTyped<c_DateTime>()->t_gettimezone(); } void f_date_timezone_set(const Object& object, const Object& timezone) { object.getTyped<c_DateTime>()->t_settimezone(timezone); } Object f_date_sub(const Object& datetime, const Object& interval) { return datetime.getTyped<c_DateTime>()-> t_sub(interval.getTyped<c_DateInterval>()); } /////////////////////////////////////////////////////////////////////////////// // sun double get_date_default_latitude() { return s_date_globals->default_latitude; } double get_date_default_longitude() { return s_date_globals->default_longitude; } double get_date_default_sunset_zenith() { return s_date_globals->sunset_zenith; } double get_date_default_sunrise_zenith() { return s_date_globals->sunrise_zenith; } double get_date_default_gmt_offset() { return s_date_extension.get_date_default_gmt_offset(); } Array f_date_sun_info(int64_t ts, double latitude, double longitude) { return DateTime(ts, false).getSunInfo(latitude, longitude); } Variant f_date_sunrise(int64_t timestamp, int format, double latitude, double longitude, double zenith, double gmt_offset) { return DateTime(timestamp, false).getSunInfo (static_cast<DateTime::SunInfoFormat>(format), latitude, longitude, zenith, gmt_offset, false); } Variant f_date_sunset(int64_t timestamp, int format, double latitude, double longitude, double zenith, double gmt_offset) { return DateTime(timestamp, false).getSunInfo (static_cast<DateTime::SunInfoFormat>(format), latitude, longitude, zenith, gmt_offset, true); } /////////////////////////////////////////////////////////////////////////////// }
namespace HPHP { /////////////////////////////////////////////////////////////////////////////// // utility functions /** * Removes whitespaces from the end, and replaces control characters with ' ' * from the beginning. */ static String php_trim(const String& str) { std::string s(str.c_str()); unsigned int l = s.length(); while (l > 0 && isspace((unsigned char)s[l - 1])) { l--; } for (unsigned int i = 0; i < l; i++) { if (iscntrl((unsigned char)s[i])) { if (i + 2 < l && s[i] == '\r' && s[i + 1] == '\n' && (s[i + 2] == ' ' || s[i + 2] == '\t')) { i += 2; while (i + 1 < l && (s[i + 1] == ' ' || s[i + 1] == '\t')) { i++; } continue; } s[i] = ' '; } } return s.substr(0, l); } bool php_mail(const String& to, const String& subject, const String& message, const String& headers, const String& extra_cmd) { // assumes we always have sendmail installed always_assert(!RuntimeOption::SendmailPath.empty()); std::ostringstream os; os << RuntimeOption::SendmailPath; if (!extra_cmd.empty()) { os << ' ' << extra_cmd.c_str(); } errno = 0; FILE *sendmail = popen(os.str().c_str(), "w"); if (sendmail == NULL || EACCES == errno) { raise_warning("Unable to execute %s", RuntimeOption::SendmailPath.c_str()); return false; } fprintf(sendmail, "To: %s\n", to.c_str()); fprintf(sendmail, "Subject: %s\n", subject.c_str()); if (!headers.empty()) { fprintf(sendmail, "%s\n", headers.c_str()); } fprintf(sendmail, "\n%s\n", message.c_str()); int ret = pclose(sendmail); return (!ret); } /////////////////////////////////////////////////////////////////////////////// const StaticString s_zero(LITSTR_INIT("\0")), s_space(" "); bool HHVM_FUNCTION(mail, const String& to, const String& subject, const String& message, const String& additional_headers /* = null_string */, const String& additional_parameters /* = null_string */) { // replace \0 with spaces String to2 = string_replace(to, s_zero, s_space); String subject2 = string_replace(subject, s_zero, s_space); String message2 = string_replace(message, s_zero, s_space); String headers2; if (!additional_headers.empty()) { headers2 = string_replace(additional_headers, s_zero, s_space); } String params2; if (!additional_parameters.empty()) { params2 = string_replace(additional_parameters, s_zero, s_space); } to2 = php_trim(to2); subject2 = php_trim(subject2); if (!RuntimeOption::MailForceExtraParameters.empty()) { params2 = string_escape_shell_cmd( RuntimeOption::MailForceExtraParameters.c_str()); } else { params2 = string_escape_shell_cmd(params2.c_str()); } return php_mail(to2, subject2, message2, headers2, params2); } int64_t HHVM_FUNCTION(ezmlm_hash, const String& addr) { unsigned int h = 5381; int str_len = addr.length(); for (int i = 0; i < str_len; i++) { h = (h + (h << 5)) ^ ((unsigned long)tolower(addr.charAt(i))); } h = (h % 53); return (int64_t)h; } /////////////////////////////////////////////////////////////////////////////// class MailExtension final : public Extension { public: MailExtension() : Extension("mail") { } void moduleInit() override { HHVM_FE(mail); HHVM_FE(ezmlm_hash); loadSystemlib(); } } s_mail_extension; /////////////////////////////////////////////////////////////////////////////// }
namespace HPHP { IMPLEMENT_DEFAULT_EXTENSION(date); /////////////////////////////////////////////////////////////////////////////// // constants const StaticString q_DateTime_ATOM(LITSTR_INIT("Y-m-d\\TH:i:sP")); const StaticString q_DateTime_COOKIE(LITSTR_INIT("l, d-M-y H:i:s T")); const StaticString q_DateTime_ISO8601(LITSTR_INIT("Y-m-d\\TH:i:sO")); const StaticString q_DateTime_RFC822(LITSTR_INIT("D, d M y H:i:s O")); const StaticString q_DateTime_RFC850(LITSTR_INIT("l, d-M-y H:i:s T")); const StaticString q_DateTime_RFC1036(LITSTR_INIT("D, d M y H:i:s O")); const StaticString q_DateTime_RFC1123(LITSTR_INIT("D, d M Y H:i:s O")); const StaticString q_DateTime_RFC2822(LITSTR_INIT("D, d M Y H:i:s O")); const StaticString q_DateTime_RFC3339(LITSTR_INIT("Y-m-d\\TH:i:sP")); const StaticString q_DateTime_RSS(LITSTR_INIT("D, d M Y H:i:s O")); const StaticString q_DateTime_W3C(LITSTR_INIT("Y-m-d\\TH:i:sP")); const int64 q_DateTimeZone_AFRICA = TimeZone::AFRICA; const int64 q_DateTimeZone_AMERICA = TimeZone::AMERICA; const int64 q_DateTimeZone_ANTARCTICA = TimeZone::ANTARCTICA; const int64 q_DateTimeZone_ARCTIC = TimeZone::ARCTIC; const int64 q_DateTimeZone_ASIA = TimeZone::ASIA; const int64 q_DateTimeZone_ATLANTIC = TimeZone::ATLANTIC; const int64 q_DateTimeZone_AUSTRALIA = TimeZone::AUSTRALIA; const int64 q_DateTimeZone_EUROPE = TimeZone::EUROPE; const int64 q_DateTimeZone_INDIAN = TimeZone::INDIAN; const int64 q_DateTimeZone_PACIFIC = TimeZone::PACIFIC; const int64 q_DateTimeZone_UTC = TimeZone::UTC; const int64 q_DateTimeZone_ALL = TimeZone::ALL; const int64 q_DateTimeZone_ALL_WITH_BC = TimeZone::ALL_WITH_BC; const int64 q_DateTimeZone_PER_COUNTRY = TimeZone::PER_COUNTRY; /////////////////////////////////////////////////////////////////////////////// // methods #define REL_TIME_INVALID_DAYS -99999 static void rel_time_to_interval(timelib_rel_time *relTime, c_DateInterval *interval) { interval->m_y = relTime->y; interval->m_m = relTime->m; interval->m_d = relTime->d; interval->m_h = relTime->h; interval->m_i = relTime->i; interval->m_s = relTime->s; interval->m_invert = relTime->invert; if (relTime->days != REL_TIME_INVALID_DAYS) { interval->m_days = relTime->days; } else { interval->m_days = null; } } static void interval_to_rel_time(c_DateInterval *interval, timelib_rel_time *relTime) { relTime->y = interval->m_y; relTime->m = interval->m_m; relTime->d = interval->m_d; relTime->h = interval->m_h; relTime->i = interval->m_i; relTime->s = interval->m_s; relTime->invert = interval->m_invert; if (interval->m_days.isInteger()) { relTime->days = interval->m_days.toInt64(); } else { relTime->days = REL_TIME_INVALID_DAYS; } } c_DateTime::c_DateTime() { } c_DateTime::~c_DateTime() { } void c_DateTime::t___construct(CStrRef time /*= "now"*/, CObjRef timezone /*= null_object*/) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::__construct); m_dt = NEWOBJ(DateTime)(TimeStamp::Current()); if (!time.empty()) { m_dt->fromString(time, c_DateTimeZone::unwrap(timezone)); } } Object c_DateTime::ti_createfromformat(const char* cls , CStrRef format, CStrRef time, CObjRef timezone /*= null_object*/) { STATIC_METHOD_INJECTION_BUILTIN(DateTime, DateTime::createfromformat); c_DateTime *datetime = NEWOBJ(c_DateTime); datetime->m_dt = NEWOBJ(DateTime); datetime->m_dt->fromString(time, c_DateTimeZone::unwrap(timezone), format.data()); return datetime; } Object c_DateTime::t_diff(CObjRef datetime2, bool absolute /*= false*/) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::diff); timelib_rel_time *relTime = m_dt->diff(*c_DateTime::unwrap(datetime2).get()); c_DateInterval *interval = NEWOBJ(c_DateInterval); rel_time_to_interval(relTime, interval); timelib_rel_time_dtor(relTime); return interval; } Object c_DateTime::t_add(CObjRef interval) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::add); c_DateInterval *tInterval = interval.getTyped<c_DateInterval>(); timelib_rel_time *relTime = timelib_rel_time_ctor(); interval_to_rel_time(tInterval, relTime); m_dt->add(*relTime); timelib_rel_time_dtor(relTime); return this; } Object c_DateTime::t_sub(CObjRef interval) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::sub); c_DateInterval *tInterval = interval.getTyped<c_DateInterval>(); timelib_rel_time *relTime = timelib_rel_time_ctor(); interval_to_rel_time(tInterval, relTime); m_dt->sub(*relTime); timelib_rel_time_dtor(relTime); return this; } String c_DateTime::t_format(CStrRef format) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::format); return m_dt->toString(format, false); } Variant c_DateTime::ti_getlasterrors(const char* cls) { STATIC_METHOD_INJECTION_BUILTIN(DateTime, DateTime::getlasterrors); return DateTime::s_last_errors->get(); } int64 c_DateTime::t_getoffset() { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::getoffset); return m_dt->offset(); } Variant c_DateTime::t_gettimezone() { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::gettimezone); SmartObject<TimeZone> tz = m_dt->timezone(); if (tz->isValid()) { return c_DateTimeZone::wrap(tz); } return false; } Object c_DateTime::t_modify(CStrRef modify) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::modify); m_dt->modify(modify); return this; } Object c_DateTime::t_setdate(int64 year, int64 month, int64 day) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::setdate); m_dt->setDate(year, month, day); return this; } Object c_DateTime::t_setisodate(int64 year, int64 week, int64 day /*= 1*/) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::setisodate); m_dt->setISODate(year, week, day); return this; } Object c_DateTime::t_settime(int64 hour, int64 minute, int64 second /*= 0*/) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::settime); m_dt->setTime(hour, minute, second); return this; } Variant c_DateTime::t_gettimestamp() { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::gettimestamp); bool err; int64 timestamp = m_dt->toTimeStamp(err); if (!err) { return timestamp; } else { return false; } } Object c_DateTime::t_settimestamp(int64 unixtimestamp) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::settimestamp); m_dt->fromTimeStamp(unixtimestamp, false); return this; } Object c_DateTime::t_settimezone(CObjRef timezone) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::settimezone); m_dt->setTimezone(c_DateTimeZone::unwrap(timezone)); return this; } Variant c_DateTime::t___destruct() { INSTANCE_METHOD_INJECTION_BUILTIN(DateTime, DateTime::__destruct); return null; } ObjectData *c_DateTime::clone() { ObjectData *obj = cloneImpl(); c_DateTime *dt = static_cast<c_DateTime*>(obj); dt->m_dt = m_dt->cloneDateTime(); return obj; } c_DateTimeZone::c_DateTimeZone() { } c_DateTimeZone::~c_DateTimeZone() { } void c_DateTimeZone::t___construct(CStrRef timezone) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::__construct); m_tz = NEWOBJ(TimeZone)(timezone); if (!m_tz->isValid()) { raise_error("DateTimeZone::__construct(): Unknown or bad timezone (%s)", timezone.data()); } } String c_DateTimeZone::t_getname() { INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::getname); return m_tz->name(); } int64 c_DateTimeZone::t_getoffset(CObjRef datetime) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::getoffset); bool error; int64 ts = c_DateTime::unwrap(datetime)->toTimeStamp(error); return m_tz->offset(ts); } Array c_DateTimeZone::t_getlocation() { INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::getlocation); return m_tz->getLocation(); } Array c_DateTimeZone::t_gettransitions(int64 timestamp_begin /*= LLONG_MIN*/, int64 timestamp_end /*= LLONG_MAX*/) { INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::gettransitions); return m_tz->transitions(timestamp_begin, timestamp_end); } Array c_DateTimeZone::ti_listabbreviations(const char* cls) { STATIC_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::listabbreviations); return TimeZone::GetAbbreviations(); } Array c_DateTimeZone::ti_listidentifiers(const char* cls, int64 what /*= 2047*/, CStrRef country /*= null_string*/) { STATIC_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::listidentifiers); return TimeZone::GetNames(what, country); } Variant c_DateTimeZone::t___destruct() { INSTANCE_METHOD_INJECTION_BUILTIN(DateTimeZone, DateTimeZone::__destruct); return null; } ObjectData *c_DateTimeZone::clone() { ObjectData *obj = cloneImpl(); c_DateTimeZone *dtz = static_cast<c_DateTimeZone*>(obj); dtz->m_tz = m_tz->cloneTimeZone(); return obj; } c_DateInterval::c_DateInterval() { } c_DateInterval::~c_DateInterval() { } void c_DateInterval::t___construct(CStrRef interval_spec) { INSTANCE_METHOD_INJECTION_BUILTIN(DateInterval, DateInterval::__construct); timelib_time *b = NULL, *e = NULL; timelib_rel_time *relTime = NULL; int r = 0; timelib_error_container *errors; timelib_strtointerval((char*)interval_spec.data(), interval_spec.size(), &b, &e, &relTime, &r, &errors); int errors1 = errors->error_count; timelib_error_container_dtor(errors); if (errors1 > 0) { timelib_rel_time_dtor(relTime); raise_error("Unknown or bad format (%s)", interval_spec.c_str()); } else { rel_time_to_interval(relTime, this); timelib_rel_time_dtor(relTime); } } Variant c_DateInterval::t___destruct() { INSTANCE_METHOD_INJECTION_BUILTIN(DateInterval, DateInterval::__destruct); return null; } Object c_DateInterval::ti_createfromdatestring(const char* cls , CStrRef time) { STATIC_METHOD_INJECTION_BUILTIN(DateInterval, DateInterval::createfromdatestring); DateTime datetime; datetime.fromString(time, SmartObject<TimeZone>()); c_DateInterval *interval = NEWOBJ(c_DateInterval); rel_time_to_interval(datetime.getRelTime(), interval); return interval; } String c_DateInterval::t_format(CStrRef format) { INSTANCE_METHOD_INJECTION_BUILTIN(DateInterval, DateInterval::format); StringBuffer s; const int LENGTH = 33; char buf[LENGTH]; int l; bool hasFormatSpec = false; for (int i = 0; i < format.length(); ++i) { char c = format.charAt(i); if (!hasFormatSpec) { if (c == '%') { hasFormatSpec = true; } else { s.append(c); } } else { switch (c) { case 'Y': l = snprintf(buf, LENGTH, "%02lld", m_y); break; case 'y': l = snprintf(buf, LENGTH, "%lld", m_y); break; case 'M': l = snprintf(buf, LENGTH, "%02lld", m_m); break; case 'm': l = snprintf(buf, LENGTH, "%lld", m_m); break; case 'D': l = snprintf(buf, LENGTH, "%02lld", m_d); break; case 'd': l = snprintf(buf, LENGTH, "%lld", m_d); break; case 'H': l = snprintf(buf, LENGTH, "%02lld", m_h); break; case 'h': l = snprintf(buf, LENGTH, "%lld", m_h); break; case 'I': l = snprintf(buf, LENGTH, "%02lld", m_i); break; case 'i': l = snprintf(buf, LENGTH, "%lld", m_i); break; case 'S': l = snprintf(buf, LENGTH, "%02lld", m_s); break; case 's': l = snprintf(buf, LENGTH, "%lld", m_s); break; case 'a': { if (m_days.isInteger()) { l = snprintf(buf, LENGTH, "%lld", m_days.toInt64()); } else { l = snprintf(buf, LENGTH, "(unknown)"); } break; } case 'r': l = snprintf(buf, LENGTH, "%s", m_invert ? "-" : ""); break; case 'R': l = snprintf(buf, LENGTH, "%c", m_invert ? '-' : '+'); break; case '%': l = snprintf(buf, 32, "%%"); break; default: buf[0] = '%'; buf[1] = c; buf[2] = '\0'; l = 2; break; } s.append(buf, std::min(l, LENGTH - 1)); hasFormatSpec = false; } } return s.detach(); } /////////////////////////////////////////////////////////////////////////////// }