00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "copyright.h"
00010 #include "autoconf.h"
00011 #include "config.h"
00012 #include "externs.h"
00013
00014 #include "ansi.h"
00015 #include "attrs.h"
00016 #include "command.h"
00017 #include "functions.h"
00018 #include "funmath.h"
00019 #include "interface.h"
00020 #include "misc.h"
00021 #include "pcre.h"
00022 #ifdef REALITY_LVLS
00023 #include "levels.h"
00024 #endif
00025
00026 UFUN *ufun_head;
00027
00028 SEP sepSpace = { 1, " " };
00029
00030
00031
00032
00033 char *trim_space_sep_LEN(char *str, int nStr, SEP *sep, int *nTrim)
00034 {
00035 if ( sep->n != 1
00036 || sep->str[0] != ' ')
00037 {
00038 *nTrim = nStr;
00039 return str;
00040 }
00041
00042
00043
00044 char *pBegin = str;
00045 char *pEnd = str + nStr - 1;
00046 while (*pBegin == ' ')
00047 {
00048 pBegin++;
00049 }
00050
00051
00052
00053 for (; pEnd > pBegin && *pEnd == ' '; pEnd--)
00054 {
00055
00056 }
00057 pEnd++;
00058
00059 *pEnd = '\0';
00060 *nTrim = pEnd - pBegin;
00061 return pBegin;
00062 }
00063
00064
00065
00066
00067 char *trim_space_sep(char *str, SEP *sep)
00068 {
00069 if ( sep->n != 1
00070 || sep->str[0] != ' ')
00071 {
00072 return str;
00073 }
00074 while (*str == ' ')
00075 {
00076 str++;
00077 }
00078 char *p;
00079 for (p = str; *p; p++)
00080 {
00081
00082 }
00083 for (p--; p > str && *p == ' '; p--)
00084 {
00085
00086 }
00087 p++;
00088 *p = '\0';
00089 return str;
00090 }
00091
00092
00093
00094
00095 static char *next_token_LEN(char *str, int *nStr, SEP *psep)
00096 {
00097 char *pBegin = str;
00098 if (psep->n == 1)
00099 {
00100 while ( *pBegin != '\0'
00101 && *pBegin != psep->str[0])
00102 {
00103 pBegin++;
00104 }
00105 if (!*pBegin)
00106 {
00107 *nStr = 0;
00108 return NULL;
00109 }
00110 pBegin++;
00111 if (psep->str[0] == ' ')
00112 {
00113 while (*pBegin == ' ')
00114 {
00115 pBegin++;
00116 }
00117 }
00118 }
00119 else
00120 {
00121 char *p = strstr(pBegin, psep->str);
00122 if (p)
00123 {
00124 pBegin = p + psep->n;
00125 }
00126 else
00127 {
00128 *nStr = 0;
00129 return NULL;
00130 }
00131 }
00132 *nStr -= pBegin - str;
00133 return pBegin;
00134 }
00135
00136
00137
00138 char *next_token(char *str, SEP *psep)
00139 {
00140 if (psep->n == 1)
00141 {
00142 while ( *str != '\0'
00143 && *str != psep->str[0])
00144 {
00145 str++;
00146 }
00147 if (!*str)
00148 {
00149 return NULL;
00150 }
00151 str++;
00152 if (psep->str[0] == ' ')
00153 {
00154 while (*str == ' ')
00155 {
00156 str++;
00157 }
00158 }
00159 }
00160 else
00161 {
00162 char *p = strstr(str, psep->str);
00163 if (p)
00164 {
00165 str = p + psep->n;
00166 }
00167 else
00168 {
00169 return NULL;
00170 }
00171 }
00172 return str;
00173 }
00174
00175
00176
00177
00178 static char *split_token_LEN(char **sp, int *nStr, SEP *psep, int *nToken)
00179 {
00180 char *str = *sp;
00181 char *save = str;
00182 if (!str)
00183 {
00184 *nStr = 0;
00185 *sp = NULL;
00186 *nToken = 0;
00187 return NULL;
00188 }
00189
00190 if (psep->n == 1)
00191 {
00192
00193
00194 while ( *str
00195 && *str != psep->str[0])
00196 {
00197 str++;
00198 }
00199 *nToken = str - save;
00200
00201 if (*str)
00202 {
00203 *str++ = '\0';
00204 if (psep->str[0] == ' ')
00205 {
00206 while (*str == ' ')
00207 {
00208 str++;
00209 }
00210 }
00211 *nStr -= str - save;
00212 }
00213 else
00214 {
00215 *nStr = 0;
00216 str = NULL;
00217 }
00218 }
00219 else
00220 {
00221 char *p = strstr(str, psep->str);
00222 if (p)
00223 {
00224 *p = '\0';
00225 str = p + psep->n;
00226 }
00227 else
00228 {
00229 str = NULL;
00230 }
00231 }
00232 *sp = str;
00233 return save;
00234 }
00235
00236
00237
00238
00239 char *split_token(char **sp, SEP *psep)
00240 {
00241 char *str = *sp;
00242 char *save = str;
00243
00244 if (!str)
00245 {
00246 *sp = NULL;
00247 return NULL;
00248 }
00249 if (psep->n == 1)
00250 {
00251 while ( *str
00252 && *str != psep->str[0])
00253 {
00254 str++;
00255 }
00256 if (*str)
00257 {
00258 *str++ = '\0';
00259 if (psep->str[0] == ' ')
00260 {
00261 while (*str == ' ')
00262 {
00263 str++;
00264 }
00265 }
00266 }
00267 else
00268 {
00269 str = NULL;
00270 }
00271 }
00272 else
00273 {
00274 char *p = strstr(str, psep->str);
00275 if (p)
00276 {
00277 *p = '\0';
00278 str = p + psep->n;
00279 }
00280 else
00281 {
00282 str = NULL;
00283 }
00284 }
00285 *sp = str;
00286 return save;
00287 }
00288
00289
00290
00291
00292
00293 #define ASCII_LIST 1
00294 #define NUMERIC_LIST 2
00295 #define DBREF_LIST 4
00296 #define FLOAT_LIST 8
00297 #define CI_ASCII_LIST 16
00298 #define ALL_LIST (ASCII_LIST|NUMERIC_LIST|DBREF_LIST|FLOAT_LIST)
00299
00300 static int autodetect_list(char *ptrs[], int nitems)
00301 {
00302 int could_be = ALL_LIST;
00303 for (int i = 0; i < nitems; i++)
00304 {
00305 char *p = ptrs[i];
00306 if (p[0] != NUMBER_TOKEN)
00307 {
00308 could_be &= ~DBREF_LIST;
00309 }
00310 if ( (could_be & DBREF_LIST)
00311 && !is_integer(p+1, NULL))
00312 {
00313 could_be &= ~(DBREF_LIST|NUMERIC_LIST|FLOAT_LIST);
00314 }
00315 if ( (could_be & FLOAT_LIST)
00316 && !is_real(p))
00317 {
00318 could_be &= ~(NUMERIC_LIST|FLOAT_LIST);
00319 }
00320 if ( (could_be & NUMERIC_LIST)
00321 && !is_integer(p, NULL))
00322 {
00323 could_be &= ~NUMERIC_LIST;
00324 }
00325
00326 if (could_be == ASCII_LIST)
00327 {
00328 return ASCII_LIST;
00329 }
00330 }
00331 if (could_be & NUMERIC_LIST)
00332 {
00333 return NUMERIC_LIST;
00334 }
00335 else if (could_be & FLOAT_LIST)
00336 {
00337 return FLOAT_LIST;
00338 }
00339 else if (could_be & DBREF_LIST)
00340 {
00341 return DBREF_LIST;
00342 }
00343 return ASCII_LIST;
00344 }
00345
00346 static int get_list_type
00347 (
00348 char *fargs[],
00349 int nfargs,
00350 int type_pos,
00351 char *ptrs[],
00352 int nitems
00353 )
00354 {
00355 if (nfargs >= type_pos)
00356 {
00357 switch (mux_tolower(*fargs[type_pos - 1]))
00358 {
00359 case 'd':
00360 return DBREF_LIST;
00361 case 'n':
00362 return NUMERIC_LIST;
00363 case 'f':
00364 return FLOAT_LIST;
00365 case 'i':
00366 return CI_ASCII_LIST;
00367 case '\0':
00368 return autodetect_list(ptrs, nitems);
00369 default:
00370 return ASCII_LIST;
00371 }
00372 }
00373 return autodetect_list(ptrs, nitems);
00374 }
00375
00376 int list2arr(char *arr[], int maxlen, char *list, SEP *psep)
00377 {
00378 list = trim_space_sep(list, psep);
00379 if (list[0] == '\0')
00380 {
00381 return 0;
00382 }
00383 char *p = split_token(&list, psep);
00384 int i;
00385 for (i = 0; p && i < maxlen; i++, p = split_token(&list, psep))
00386 {
00387 arr[i] = p;
00388 }
00389 return i;
00390 }
00391
00392 void arr2list(char *arr[], int alen, char *list, char **bufc, SEP *psep)
00393 {
00394 int i;
00395 for (i = 0; i < alen-1; i++)
00396 {
00397 safe_str(arr[i], list, bufc);
00398 print_sep(psep, list, bufc);
00399 }
00400 if (alen)
00401 {
00402 safe_str(arr[i], list, bufc);
00403 }
00404 }
00405
00406 static int dbnum(char *dbr)
00407 {
00408 if (dbr[0] != '#' || dbr[1] == '\0')
00409 {
00410 return 0;
00411 }
00412 else
00413 {
00414 return mux_atol(dbr + 1);
00415 }
00416 }
00417
00418
00419
00420
00421
00422 static bool nearby_or_control(dbref player, dbref thing)
00423 {
00424 if (!Good_obj(player) || !Good_obj(thing))
00425 {
00426 return false;
00427 }
00428 if (Controls(player, thing))
00429 {
00430 return true;
00431 }
00432 if (!nearby(player, thing))
00433 {
00434 return false;
00435 }
00436 return true;
00437 }
00438
00439
00440
00441
00442 bool delim_check
00443 (
00444 char *buff, char **bufc,
00445 dbref executor, dbref caller, dbref enactor,
00446 char *fargs[], int nfargs,
00447 char *cargs[], int ncargs,
00448 int sep_arg, SEP *sep, int dflags
00449 )
00450 {
00451 bool bSuccess = true;
00452 if (sep_arg <= nfargs)
00453 {
00454
00455
00456 char *tstr = fargs[sep_arg-1];
00457 int tlen = strlen(tstr);
00458
00459 if (tlen <= 1)
00460 {
00461 dflags &= ~DELIM_EVAL;
00462 }
00463 if (dflags & DELIM_EVAL)
00464 {
00465 char *str = tstr;
00466 char *bp = tstr = alloc_lbuf("delim_check");
00467 mux_exec(tstr, &bp, executor, caller, enactor,
00468 EV_EVAL | EV_FCHECK, &str, cargs, ncargs);
00469 *bp = '\0';
00470 tlen = bp - tstr;
00471 }
00472
00473
00474
00475
00476 if (tlen == 1)
00477 {
00478 sep->n = 1;
00479 memcpy(sep->str, tstr, tlen+1);
00480 }
00481 else if (tlen == 0)
00482 {
00483 sep->n = 1;
00484 memcpy(sep->str, " ", 2);
00485 }
00486 else if ( tlen == 2
00487 && (dflags & DELIM_NULL)
00488 && memcmp(tstr, NULL_DELIM_VAR, 2) == 0)
00489 {
00490 sep->n = 0;
00491 sep->str[0] = '\0';
00492 }
00493 else if ( tlen == 2
00494 && (dflags & DELIM_EVAL)
00495 && memcmp(tstr, "\r\n", 2) == 0)
00496 {
00497 sep->n = 2;
00498 memcpy(sep->str, "\r\n", 3);
00499 }
00500 else if (dflags & DELIM_STRING)
00501 {
00502 if (tlen <= MAX_SEP_LEN)
00503 {
00504 sep->n = tlen;
00505 memcpy(sep->str, tstr, tlen);
00506 sep->str[sep->n] = '\0';
00507 }
00508 else
00509 {
00510 safe_str("#-1 SEPARATOR IS TOO LARGE", buff, bufc);
00511 bSuccess = false;
00512 }
00513 }
00514 else
00515 {
00516 safe_str("#-1 SEPARATOR MUST BE ONE CHARACTER", buff, bufc);
00517 bSuccess = false;
00518 }
00519
00520
00521
00522 if (dflags & DELIM_EVAL)
00523 {
00524 free_lbuf(tstr);
00525 }
00526 }
00527 else if (!(dflags & DELIM_INIT))
00528 {
00529 sep->n = 1;
00530 memcpy(sep->str, " ", 2);
00531 }
00532 return bSuccess;
00533 }
00534
00535
00536
00537
00538
00539
00540 int countwords(char *str, SEP *psep)
00541 {
00542 int n;
00543
00544 str = trim_space_sep(str, psep);
00545 if (!*str)
00546 {
00547 return 0;
00548 }
00549 for (n = 0; str; str = next_token(str, psep), n++)
00550 {
00551 ;
00552 }
00553 return n;
00554 }
00555
00556 static FUNCTION(fun_words)
00557 {
00558 if (nfargs == 0)
00559 {
00560 safe_chr('0', buff, bufc);
00561 return;
00562 }
00563
00564 SEP sep;
00565 if (!OPTIONAL_DELIM(2, sep, DELIM_DFLT|DELIM_STRING))
00566 {
00567 return;
00568 }
00569
00570 safe_ltoa(countwords(strip_ansi(fargs[0]), &sep), buff, bufc);
00571 }
00572
00573
00574
00575
00576
00577
00578 static FUNCTION(fun_flags)
00579 {
00580 UNUSED_PARAMETER(caller);
00581 UNUSED_PARAMETER(nfargs);
00582 UNUSED_PARAMETER(cargs);
00583 UNUSED_PARAMETER(ncargs);
00584
00585 dbref it;
00586 ATTR *pattr;
00587 if (parse_attrib(executor, fargs[0], &it, &pattr))
00588 {
00589 if ( pattr
00590 && See_attr(executor, it, pattr))
00591 {
00592 dbref aowner;
00593 int aflags;
00594 atr_pget_info(it, pattr->number, &aowner, &aflags);
00595 char xbuf[11];
00596 decode_attr_flags(aflags, xbuf);
00597 safe_str(xbuf, buff, bufc);
00598 }
00599 }
00600 else
00601 {
00602 it = match_thing_quiet(executor, fargs[0]);
00603 if (!Good_obj(it))
00604 {
00605 safe_match_result(it, buff, bufc);
00606 return;
00607 }
00608 if ( mudconf.pub_flags
00609 || Examinable(executor, it)
00610 || it == enactor)
00611 {
00612 char *buff2 = decode_flags(executor, &(db[it].fs));
00613 safe_str(buff2, buff, bufc);
00614 free_sbuf(buff2);
00615 }
00616 else
00617 {
00618 safe_noperm(buff, bufc);
00619 }
00620 }
00621 }
00622
00623
00624
00625
00626
00627 static FUNCTION(fun_rand)
00628 {
00629 UNUSED_PARAMETER(executor);
00630 UNUSED_PARAMETER(caller);
00631 UNUSED_PARAMETER(enactor);
00632 UNUSED_PARAMETER(cargs);
00633 UNUSED_PARAMETER(ncargs);
00634
00635 int nDigits;
00636 switch (nfargs)
00637 {
00638 case 1:
00639 if (is_integer(fargs[0], &nDigits))
00640 {
00641 int num = mux_atol(fargs[0]);
00642 if (num < 1)
00643 {
00644 safe_chr('0', buff, bufc);
00645 }
00646 else
00647 {
00648 safe_ltoa(RandomINT32(0, num-1), buff, bufc);
00649 }
00650 }
00651 else
00652 {
00653 safe_str("#-1 ARGUMENT MUST BE INTEGER", buff, bufc);
00654 }
00655 break;
00656
00657 case 2:
00658 if ( is_integer(fargs[0], &nDigits)
00659 && is_integer(fargs[1], &nDigits))
00660 {
00661 int lower = mux_atol(fargs[0]);
00662 int higher = mux_atol(fargs[1]);
00663 if ( lower <= higher
00664 && (unsigned int)(higher-lower) <= INT32_MAX_VALUE)
00665 {
00666 safe_ltoa(RandomINT32(lower, higher), buff, bufc);
00667 }
00668 else
00669 {
00670 safe_range(buff, bufc);
00671 }
00672 }
00673 else
00674 {
00675 safe_str("#-1 ARGUMENT MUST BE INTEGER", buff, bufc);
00676 }
00677 break;
00678 }
00679 }
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 static FUNCTION(fun_time)
00691 {
00692 UNUSED_PARAMETER(executor);
00693 UNUSED_PARAMETER(caller);
00694 UNUSED_PARAMETER(enactor);
00695 UNUSED_PARAMETER(cargs);
00696 UNUSED_PARAMETER(ncargs);
00697
00698 CLinearTimeAbsolute ltaNow;
00699 if ( nfargs == 0
00700 || mux_stricmp("utc", fargs[0]) != 0)
00701 {
00702 ltaNow.GetLocal();
00703 }
00704 else
00705 {
00706 ltaNow.GetUTC();
00707 }
00708 int nPrecision = 0;
00709 if (nfargs == 2)
00710 {
00711 nPrecision = mux_atol(fargs[1]);
00712 }
00713 char *temp = ltaNow.ReturnDateString(nPrecision);
00714 safe_str(temp, buff, bufc);
00715 }
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 static FUNCTION(fun_secs)
00729 {
00730 UNUSED_PARAMETER(executor);
00731 UNUSED_PARAMETER(caller);
00732 UNUSED_PARAMETER(enactor);
00733 UNUSED_PARAMETER(cargs);
00734 UNUSED_PARAMETER(ncargs);
00735
00736 CLinearTimeAbsolute ltaNow;
00737 if ( nfargs == 0
00738 || mux_stricmp("local", fargs[0]) != 0)
00739 {
00740 ltaNow.GetUTC();
00741 }
00742 else
00743 {
00744 ltaNow.GetLocal();
00745 }
00746 int nPrecision = 0;
00747 if (nfargs == 2)
00748 {
00749 nPrecision = mux_atol(fargs[1]);
00750 }
00751 safe_str(ltaNow.ReturnSecondsString(nPrecision), buff, bufc);
00752 }
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769 static FUNCTION(fun_convsecs)
00770 {
00771 UNUSED_PARAMETER(executor);
00772 UNUSED_PARAMETER(caller);
00773 UNUSED_PARAMETER(enactor);
00774 UNUSED_PARAMETER(cargs);
00775 UNUSED_PARAMETER(ncargs);
00776
00777 CLinearTimeAbsolute lta;
00778 if (lta.SetSecondsString(fargs[0]))
00779 {
00780 if ( nfargs == 1
00781 || mux_stricmp("utc", fargs[1]) != 0)
00782 {
00783 lta.UTC2Local();
00784 }
00785 int nPrecision = 0;
00786 if (nfargs == 3)
00787 {
00788 nPrecision = mux_atol(fargs[2]);
00789 }
00790 char *temp = lta.ReturnDateString(nPrecision);
00791 safe_str(temp, buff, bufc);
00792 }
00793 else
00794 {
00795 safe_str("#-1 INVALID DATE", buff, bufc);
00796 }
00797 }
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817 static FUNCTION(fun_convtime)
00818 {
00819 UNUSED_PARAMETER(executor);
00820 UNUSED_PARAMETER(caller);
00821 UNUSED_PARAMETER(enactor);
00822 UNUSED_PARAMETER(cargs);
00823 UNUSED_PARAMETER(ncargs);
00824
00825 CLinearTimeAbsolute lta;
00826 bool bZoneSpecified = false;
00827 if ( lta.SetString(fargs[0])
00828 || ParseDate(lta, fargs[0], &bZoneSpecified))
00829 {
00830 if ( !bZoneSpecified
00831 && ( nfargs == 1
00832 || mux_stricmp("utc", fargs[1]) != 0))
00833 {
00834 lta.Local2UTC();
00835 }
00836 int nPrecision = 0;
00837 if (nfargs == 3)
00838 {
00839 nPrecision = mux_atol(fargs[2]);
00840 }
00841 safe_str(lta.ReturnSecondsString(nPrecision), buff, bufc);
00842 }
00843 else
00844 {
00845 safe_str("#-1 INVALID DATE", buff, bufc);
00846 }
00847 }
00848
00849
00850
00851
00852
00853
00854 static FUNCTION(fun_starttime)
00855 {
00856 UNUSED_PARAMETER(executor);
00857 UNUSED_PARAMETER(caller);
00858 UNUSED_PARAMETER(enactor);
00859 UNUSED_PARAMETER(fargs);
00860 UNUSED_PARAMETER(nfargs);
00861 UNUSED_PARAMETER(cargs);
00862 UNUSED_PARAMETER(ncargs);
00863
00864 char *temp = mudstate.start_time.ReturnDateString();
00865 safe_str(temp, buff, bufc);
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879 static const char *DayOfWeekStringLong[7] =
00880 {
00881 "Sunday",
00882 "Monday",
00883 "Tuesday",
00884 "Wednesday",
00885 "Thursday",
00886 "Friday",
00887 "Saturday"
00888 };
00889
00890 static const char *MonthTableLong[] =
00891 {
00892 "January",
00893 "February",
00894 "March",
00895 "April",
00896 "May",
00897 "June",
00898 "July",
00899 "August",
00900 "September",
00901 "October",
00902 "November",
00903 "December"
00904 };
00905
00906 static const int Map24to12[24] =
00907 {
00908 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
00909 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
00910 };
00911
00912 static FUNCTION(fun_timefmt)
00913 {
00914 UNUSED_PARAMETER(executor);
00915 UNUSED_PARAMETER(caller);
00916 UNUSED_PARAMETER(enactor);
00917 UNUSED_PARAMETER(cargs);
00918 UNUSED_PARAMETER(ncargs);
00919
00920 CLinearTimeAbsolute lta, ltaUTC;
00921 if (nfargs == 2)
00922 {
00923 ltaUTC.SetSecondsString(fargs[1]);
00924 }
00925 else
00926 {
00927 ltaUTC.GetUTC();
00928 }
00929 lta = ltaUTC;
00930 lta.UTC2Local();
00931
00932 FIELDEDTIME ft;
00933 lta.ReturnFields(&ft);
00934
00935
00936
00937 CLinearTimeDelta ltd = lta - ltaUTC;
00938 int iTZSecond = ltd.ReturnSeconds();
00939 int iTZSign;
00940 if (iTZSecond < 0)
00941 {
00942 iTZSign = '-';
00943 iTZSecond = -iTZSecond;
00944 }
00945 else
00946 {
00947 iTZSign = '+';
00948 }
00949 int iTZHour = iTZSecond / 3600;
00950 iTZSecond %= 3600;
00951 int iTZMinute = iTZSecond/60;
00952 int iHour12 = Map24to12[ft.iHour];
00953
00954
00955
00956 int iWeekOfYearSunday = (ft.iDayOfYear-ft.iDayOfWeek+6)/7;
00957 int iDayOfWeekMonday = (ft.iDayOfWeek == 0)?7:ft.iDayOfWeek;
00958 int iWeekOfYearMonday = (ft.iDayOfYear-iDayOfWeekMonday+7)/7;
00959
00960
00961
00962
00963 int iYearISO = ft.iYear;
00964 int iWeekISO = 0;
00965 int iTemp = 0;
00966 if ( ft.iMonth == 12
00967 && 35 <= 7 + ft.iDayOfMonth - iDayOfWeekMonday)
00968 {
00969 iYearISO++;
00970 iWeekISO = 1;
00971 }
00972 else if ( ft.iMonth == 1
00973 && ft.iDayOfMonth <= 3
00974 && (iTemp = 7 - ft.iDayOfMonth + iDayOfWeekMonday) >= 11)
00975 {
00976 iYearISO--;
00977 if ( iTemp == 11
00978 || ( iTemp == 12
00979 && isLeapYear(iYearISO)))
00980 {
00981 iWeekISO = 53;
00982 }
00983 else
00984 {
00985 iWeekISO = 52;
00986 }
00987 }
00988 else
00989 {
00990 iWeekISO = (7 + ft.iDayOfYear - iDayOfWeekMonday)/7;
00991 if (4 <= (7 + ft.iDayOfYear - iDayOfWeekMonday)%7)
00992 {
00993 iWeekISO++;
00994 }
00995 }
00996
00997 char *q;
00998 char *p = fargs[0];
00999 while ((q = strchr(p, '$')) != NULL)
01000 {
01001 size_t nLen = q - p;
01002 safe_copy_buf(p, nLen, buff, bufc);
01003 p = q;
01004
01005
01006
01007 p++;
01008
01009
01010
01011 int iOption = 0;
01012 int ch = *p++;
01013 if (ch == '#' || ch == 'E' || ch == 'O')
01014 {
01015 iOption = ch;
01016 ch = *p++;
01017 }
01018
01019
01020
01021 switch (ch)
01022 {
01023 case 'a':
01024 safe_str(DayOfWeekString[ft.iDayOfWeek], buff, bufc);
01025 break;
01026
01027 case 'A':
01028 safe_str(DayOfWeekStringLong[ft.iDayOfWeek], buff, bufc);
01029 break;
01030
01031 case 'b':
01032 case 'h':
01033 safe_str(monthtab[ft.iMonth-1], buff, bufc);
01034 break;
01035
01036 case 'B':
01037 safe_str(MonthTableLong[ft.iMonth-1], buff, bufc);
01038 break;
01039
01040 case 'c':
01041 if (iOption == '#')
01042 {
01043
01044
01045 safe_tprintf_str(buff, bufc, "%s, %s %d, %d, %02d:%02d:%02d",
01046 DayOfWeekStringLong[ft.iDayOfWeek],
01047 MonthTableLong[ft.iMonth-1],
01048 ft.iDayOfMonth, ft.iYear, ft.iHour, ft.iMinute,
01049 ft.iSecond);
01050 }
01051 else
01052 {
01053 safe_str(lta.ReturnDateString(7), buff, bufc);
01054 }
01055 break;
01056
01057 case 'C':
01058 safe_tprintf_str(buff, bufc, "%d", ft.iYear / 100);
01059 break;
01060
01061 case 'd':
01062 safe_tprintf_str(buff, bufc, (iOption=='#')?"%d":"%02d",
01063 ft.iDayOfMonth);
01064 break;
01065
01066 case 'x':
01067 if (iOption == '#')
01068 {
01069 safe_tprintf_str(buff, bufc, "%s, %s %d, %d",
01070 DayOfWeekStringLong[ft.iDayOfWeek],
01071 MonthTableLong[ft.iMonth-1],
01072 ft.iDayOfMonth, ft.iYear);
01073 break;
01074 }
01075
01076
01077
01078 case 'D':
01079 safe_tprintf_str(buff, bufc, "%02d/%02d/%02d", ft.iMonth,
01080 ft.iDayOfMonth, ft.iYear % 100);
01081 break;
01082
01083 case 'e':
01084
01085 safe_tprintf_str(buff, bufc, "%2d", ft.iDayOfMonth);
01086 break;
01087
01088 case 'F':
01089 safe_tprintf_str(buff, bufc, "%d-%02d-%02d", ft.iYear, ft.iMonth,
01090 ft.iDayOfMonth);
01091 break;
01092
01093 case 'g':
01094 safe_tprintf_str(buff, bufc, "%02d", iYearISO%100);
01095 break;
01096
01097 case 'G':
01098 safe_tprintf_str(buff, bufc, "%04d", iYearISO);
01099 break;
01100
01101 case 'H':
01102 safe_tprintf_str(buff, bufc, (iOption=='#')?"%d":"%02d", ft.iHour);
01103 break;
01104
01105 case 'I':
01106 safe_tprintf_str(buff, bufc, (iOption=='#')?"%d":"%02d", iHour12);
01107 break;
01108
01109 case 'j':
01110 safe_tprintf_str(buff, bufc, (iOption=='#')?"%d":"%03d",
01111 ft.iDayOfYear);
01112 break;
01113
01114 case 'k':
01115 safe_tprintf_str(buff, bufc, "%2d", ft.iHour);
01116 break;
01117
01118 case 'l':
01119 safe_tprintf_str(buff, bufc, "%2d", iHour12);
01120 break;
01121
01122 case 'm':
01123 safe_tprintf_str(buff, bufc, (iOption=='#')?"%d":"%02d",
01124 ft.iMonth);
01125 break;
01126
01127 case 'M':
01128 safe_tprintf_str(buff, bufc, (iOption=='#')?"%d":"%02d",
01129 ft.iMinute);
01130 break;
01131
01132 case 'n':
01133 safe_str("\r\n", buff, bufc);
01134 break;
01135
01136 case 'p':
01137 safe_str((ft.iHour < 12)?"AM":"PM", buff, bufc);
01138 break;
01139
01140 case 'P':
01141 safe_str((ft.iHour < 12)?"am":"pm", buff, bufc);
01142 break;
01143
01144 case 'r':
01145 safe_tprintf_str(buff, bufc,
01146 (iOption=='#')?"%d:%02d:%02d %s":"%02d:%02d:%02d %s",
01147 iHour12, ft.iMinute, ft.iSecond,
01148 (ft.iHour<12)?"AM":"PM");
01149 break;
01150
01151 case 'R':
01152 safe_tprintf_str(buff, bufc, (iOption=='#')?"%d:%02d":"%02d:%02d",
01153 ft.iHour, ft.iMinute);
01154 break;
01155
01156 case 's':
01157 safe_str(ltaUTC.ReturnSecondsString(7), buff, bufc);
01158 break;
01159
01160 case 'S':
01161 safe_tprintf_str(buff, bufc, (iOption=='#')?"%d":"%02d",
01162 ft.iSecond);
01163 break;
01164
01165 case 't':
01166 safe_chr('\t', buff, bufc);
01167 break;
01168
01169 case 'X':
01170 case 'T':
01171 safe_tprintf_str(buff, bufc,
01172 (iOption=='#')?"%d:%02d:%02d":"%02d:%02d:%02d",
01173 ft.iHour, ft.iMinute, ft.iSecond);
01174 break;
01175
01176 case 'u':
01177 safe_ltoa(iDayOfWeekMonday, buff, bufc);
01178 break;
01179
01180 case 'U':
01181 safe_tprintf_str(buff, bufc, (iOption=='#')?"%d":"%02d",
01182 iWeekOfYearSunday);
01183 break;
01184
01185 case 'V':
01186 safe_tprintf_str(buff, bufc, "%02d", iWeekISO);
01187 break;
01188
01189 case 'w':
01190 safe_ltoa(ft.iDayOfWeek, buff, bufc);
01191 break;
01192
01193 case 'W':
01194 safe_tprintf_str(buff, bufc, (iOption=='#')?"%d":"%02d",
01195 iWeekOfYearMonday);
01196 break;
01197
01198 case 'y':
01199 safe_tprintf_str(buff, bufc, (iOption=='#')?"%d":"%02d",
01200 ft.iYear % 100);
01201 break;
01202
01203 case 'Y':
01204 safe_tprintf_str(buff, bufc, (iOption=='#')?"%d":"%04d",
01205 ft.iYear);
01206 break;
01207
01208 case 'z':
01209 safe_tprintf_str(buff, bufc, "%c%02d%02d", iTZSign, iTZHour,
01210 iTZMinute);
01211 break;
01212
01213 case 'Z':
01214
01215 break;
01216
01217 case '$':
01218 safe_chr(ch, buff, bufc);
01219 break;
01220
01221 default:
01222 safe_chr('$', buff, bufc);
01223 p = q + 1;
01224 break;
01225 }
01226 }
01227 safe_str(p, buff, bufc);
01228 }
01229
01230
01231
01232
01233
01234 #define GET_GET 1
01235 #define GET_XGET 2
01236 #define GET_EVAL 4
01237 #define GET_GEVAL 8
01238
01239 static void get_handler(char *buff, char **bufc, dbref executor, char *fargs[], int key)
01240 {
01241 bool bFreeBuffer = false;
01242 char *pRefAttrib = fargs[0];
01243
01244 if ( key == GET_XGET
01245 || key == GET_EVAL)
01246 {
01247 pRefAttrib = alloc_lbuf("get_handler");
01248 char *bufp = pRefAttrib;
01249 safe_tprintf_str(pRefAttrib, &bufp, "%s/%s", fargs[0], fargs[1]);
01250 bFreeBuffer = true;
01251 }
01252 dbref thing;
01253 ATTR *pattr;
01254 bool bNoMatch = !parse_attrib(executor, pRefAttrib, &thing, &pattr);
01255 if (bFreeBuffer)
01256 {
01257 free_lbuf(pRefAttrib);
01258 }
01259
01260 if (bNoMatch)
01261 {
01262 safe_nomatch(buff, bufc);
01263 return;
01264 }
01265
01266 if (!pattr)
01267 {
01268 return;
01269 }
01270
01271 if ( (pattr->flags & AF_IS_LOCK)
01272 || !bCanReadAttr(executor, thing, pattr, true))
01273 {
01274 safe_noperm(buff, bufc);
01275 return;
01276 }
01277
01278 dbref aowner;
01279 int aflags;
01280 size_t nLen = 0;
01281 char *atr_gotten = atr_pget_LEN(thing, pattr->number, &aowner, &aflags, &nLen);
01282
01283 if ( key == GET_EVAL
01284 || key == GET_GEVAL)
01285 {
01286 char *str = atr_gotten;
01287 mux_exec(buff, bufc, thing, executor, executor, EV_FIGNORE | EV_EVAL,
01288 &str, (char **)NULL, 0);
01289 }
01290 else
01291 {
01292 if (nLen)
01293 {
01294 safe_copy_buf(atr_gotten, nLen, buff, bufc);
01295 }
01296 }
01297 free_lbuf(atr_gotten);
01298 }
01299
01300 static FUNCTION(fun_get)
01301 {
01302 UNUSED_PARAMETER(caller);
01303 UNUSED_PARAMETER(enactor);
01304 UNUSED_PARAMETER(nfargs);
01305 UNUSED_PARAMETER(cargs);
01306 UNUSED_PARAMETER(ncargs);
01307
01308 get_handler(buff, bufc, executor, fargs, GET_GET);
01309 }
01310
01311 static FUNCTION(fun_xget)
01312 {
01313 UNUSED_PARAMETER(caller);
01314 UNUSED_PARAMETER(enactor);
01315 UNUSED_PARAMETER(nfargs);
01316 UNUSED_PARAMETER(cargs);
01317 UNUSED_PARAMETER(ncargs);
01318
01319 if (!*fargs[0] || !*fargs[1])
01320 {
01321