00001
00002
00003
00004
00005 #include "copyright.h"
00006 #include "autoconf.h"
00007 #include "config.h"
00008 #include "externs.h"
00009
00010 #include <sys/types.h>
00011
00012 #include "ansi.h"
00013 #include "attrs.h"
00014 #include "command.h"
00015 #include "comsys.h"
00016 #include "functions.h"
00017 #include "interface.h"
00018 #include "powers.h"
00019
00020 static int num_channels;
00021 static comsys_t *comsys_table[NUM_COMSYS];
00022
00023 #define DFLT_MAX_LOG 0
00024 #define MIN_RECALL_REQUEST 1
00025 #define DFLT_RECALL_REQUEST 10
00026 #define MAX_RECALL_REQUEST 200
00027
00028
00029
00030 static char *RestrictTitleValue(char *pTitleRequest)
00031 {
00032
00033
00034 char *pNewTitle = RemoveSetOfCharacters(pTitleRequest, "\r\n\t");
00035
00036
00037
00038 char NewTitle_ANSI[MAX_TITLE_LEN+1];
00039 int nVisualWidth;
00040 int nLen = ANSI_TruncateToField(pNewTitle, sizeof(NewTitle_ANSI),
00041 NewTitle_ANSI, sizeof(NewTitle_ANSI), &nVisualWidth,
00042 ANSI_ENDGOAL_NORMAL);
00043 memcpy(pNewTitle, NewTitle_ANSI, nLen+1);
00044 return pNewTitle;
00045 }
00046
00047 static void do_setcomtitlestatus(dbref player, struct channel *ch, bool status)
00048 {
00049 struct comuser *user = select_user(ch,player);
00050 if (ch && user)
00051 {
00052 user->ComTitleStatus = status;
00053 }
00054 }
00055
00056 static void do_setnewtitle(dbref player, struct channel *ch, char *pValidatedTitle)
00057 {
00058 struct comuser *user = select_user(ch, player);
00059
00060 if (ch && user)
00061 {
00062 if (user->title)
00063 {
00064 MEMFREE(user->title);
00065 user->title = NULL;
00066 }
00067 user->title = StringClone(pValidatedTitle);
00068 }
00069 }
00070
00071 void load_comsys(char *filename)
00072 {
00073 int i;
00074 char buffer[200];
00075
00076 for (i = 0; i < NUM_COMSYS; i++)
00077 {
00078 comsys_table[i] = NULL;
00079 }
00080
00081 FILE *fp = fopen(filename, "rb");
00082 if (!fp)
00083 {
00084 Log.tinyprintf("Error: Couldn't find %s." ENDLINE, filename);
00085 }
00086 else
00087 {
00088 DebugTotalFiles++;
00089 Log.tinyprintf("LOADING: %s" ENDLINE, filename);
00090 if (fscanf(fp, "*** Begin %s ***\n", buffer) == 1 && !strcmp(buffer, "CHANNELS"))
00091 {
00092 load_channels(fp);
00093 }
00094 else
00095 {
00096 Log.tinyprintf("Error: Couldn't find Begin CHANNELS in %s.", filename);
00097 if (fclose(fp) == 0)
00098 {
00099 DebugTotalFiles--;
00100 }
00101 return;
00102 }
00103
00104 if (fscanf(fp, "*** Begin %s ***\n", buffer) == 1 && !strcmp(buffer, "COMSYS"))
00105 {
00106 load_comsystem(fp);
00107 }
00108 else
00109 {
00110 Log.tinyprintf("Error: Couldn't find Begin COMSYS in %s.", filename);
00111 if (fclose(fp) == 0)
00112 {
00113 DebugTotalFiles--;
00114 }
00115 return;
00116 }
00117
00118 if (fclose(fp) == 0)
00119 {
00120 DebugTotalFiles--;
00121 }
00122 Log.tinyprintf("LOADING: %s (done)" ENDLINE, filename);
00123 }
00124 }
00125
00126 void save_comsys(char *filename)
00127 {
00128 char buffer[500];
00129
00130 sprintf(buffer, "%s.#", filename);
00131 FILE *fp = fopen(buffer, "wb");
00132 if (!fp)
00133 {
00134 Log.tinyprintf("Unable to open %s for writing." ENDLINE, buffer);
00135 return;
00136 }
00137 DebugTotalFiles++;
00138 fprintf(fp, "*** Begin CHANNELS ***\n");
00139 save_channels(fp);
00140
00141 fprintf(fp, "*** Begin COMSYS ***\n");
00142 save_comsystem(fp);
00143
00144 if (fclose(fp) == 0)
00145 {
00146 DebugTotalFiles--;
00147 }
00148 ReplaceFile(buffer, filename);
00149 }
00150
00151
00152
00153 static char *MakeCanonicalComAlias
00154 (
00155 const char *pAlias,
00156 int *nValidAlias,
00157 bool *bValidAlias
00158 )
00159 {
00160 static char Buffer[ALIAS_SIZE];
00161 *nValidAlias = 0;
00162 *bValidAlias = false;
00163
00164 if (!pAlias)
00165 {
00166 return NULL;
00167 }
00168 const char *p = pAlias;
00169 char *q = Buffer;
00170 int n = 0;
00171 while (*p)
00172 {
00173 if ( !mux_isprint(*p)
00174 || *p == ' ')
00175 {
00176 return NULL;
00177 }
00178 if ( n <= MAX_ALIAS_LEN
00179 && q < Buffer + ALIAS_SIZE)
00180 {
00181 n++;
00182 *q++ = *p;
00183 }
00184 p++;
00185 }
00186 *q = '\0';
00187 if ( n < 1
00188 || MAX_ALIAS_LEN < n)
00189 {
00190 return NULL;
00191 }
00192 *nValidAlias = n;
00193 *bValidAlias = true;
00194 return Buffer;
00195 }
00196
00197 static bool ParseChannelLine(char *pBuffer, char *pAlias5, char **ppChannelName)
00198 {
00199
00200
00201 char *p = strchr(pBuffer, ' ');
00202 if (!p)
00203 {
00204 return false;
00205 }
00206
00207 *p = '\0';
00208 bool bValidAlias;
00209 int nValidAlias;
00210 char *pValidAlias = MakeCanonicalComAlias(pBuffer, &nValidAlias, &bValidAlias);
00211 if (!bValidAlias)
00212 {
00213 return false;
00214 }
00215 strcpy(pAlias5, pValidAlias);
00216
00217
00218
00219 p++;
00220 while (mux_isspace(*p))
00221 {
00222 p++;
00223 }
00224
00225 if (*p == '\0')
00226 {
00227 return false;
00228 }
00229
00230
00231
00232 *ppChannelName = StringClone(p);
00233 return true;
00234 }
00235
00236 void load_channels(FILE *fp)
00237 {
00238 int i, j;
00239 char buffer[LBUF_SIZE];
00240 comsys_t *c;
00241
00242 int np = 0;
00243 int cc = fscanf(fp, "%d\n", &np);
00244 mux_assert(1 == cc);
00245 for (i = 0; i < np; i++)
00246 {
00247 c = create_new_comsys();
00248 c->who = 0;
00249 c->numchannels = 0;
00250 cc = fscanf(fp, "%d %d\n", &(c->who), &(c->numchannels));
00251 mux_assert(2 == cc);
00252 c->maxchannels = c->numchannels;
00253 if (c->maxchannels > 0)
00254 {
00255 c->alias = (char *)MEMALLOC(c->maxchannels * ALIAS_SIZE);
00256 ISOUTOFMEMORY(c->alias);
00257 c->channels = (char **)MEMALLOC(sizeof(char *) * c->maxchannels);
00258 ISOUTOFMEMORY(c->channels);
00259
00260 for (j = 0; j < c->numchannels; j++)
00261 {
00262 int n = GetLineTrunc(buffer, sizeof(buffer), fp);
00263 if (buffer[n-1] == '\n')
00264 {
00265
00266
00267 n--;
00268 buffer[n] = '\0';
00269 }
00270 if (!ParseChannelLine(buffer, c->alias + j * ALIAS_SIZE, c->channels+j))
00271 {
00272 c->numchannels--;
00273 j--;
00274 }
00275 }
00276 sort_com_aliases(c);
00277 }
00278 else
00279 {
00280 c->alias = NULL;
00281 c->channels = NULL;
00282 }
00283 if (Good_obj(c->who))
00284 {
00285 add_comsys(c);
00286 }
00287 else
00288 {
00289 Log.tinyprintf("Invalid dbref %d." ENDLINE, c->who);
00290 }
00291 purge_comsystem();
00292 }
00293 }
00294
00295 void purge_comsystem(void)
00296 {
00297 #ifdef ABORT_PURGE_COMSYS
00298 return;
00299 #endif // ABORT_PURGE_COMSYS
00300
00301 comsys_t *c;
00302 comsys_t *d;
00303 int i;
00304 for (i = 0; i < NUM_COMSYS; i++)
00305 {
00306 c = comsys_table[i];
00307 while (c)
00308 {
00309 d = c;
00310 c = c->next;
00311 if (d->numchannels == 0)
00312 {
00313 del_comsys(d->who);
00314 continue;
00315 }
00316 if (isPlayer(d->who))
00317 {
00318 continue;
00319 }
00320 if ( God(Owner(d->who))
00321 && Going(d->who))
00322 {
00323 del_comsys(d->who);
00324 continue;
00325 }
00326 }
00327 }
00328 }
00329
00330 void save_channels(FILE *fp)
00331 {
00332 purge_comsystem();
00333
00334 comsys_t *c;
00335 int i, j;
00336 int np = 0;
00337 for (i = 0; i < NUM_COMSYS; i++)
00338 {
00339 c = comsys_table[i];
00340 while (c)
00341 {
00342 np++;
00343 c = c->next;
00344 }
00345 }
00346
00347 fprintf(fp, "%d\n", np);
00348 for (i = 0; i < NUM_COMSYS; i++)
00349 {
00350 c = comsys_table[i];
00351 while (c)
00352 {
00353 fprintf(fp, "%d %d\n", c->who, c->numchannels);
00354 for (j = 0; j < c->numchannels; j++)
00355 {
00356 fprintf(fp, "%s %s\n", c->alias + j * ALIAS_SIZE, c->channels[j]);
00357 }
00358 c = c->next;
00359 }
00360 }
00361 }
00362
00363 comsys_t *create_new_comsys(void)
00364 {
00365 comsys_t *c = (comsys_t *)MEMALLOC(sizeof(comsys_t));
00366 ISOUTOFMEMORY(c);
00367
00368 c->who = NOTHING;
00369 c->numchannels = 0;
00370 c->maxchannels = 0;
00371 c->alias = NULL;
00372 c->channels = NULL;
00373 c->next = NULL;
00374 return c;
00375 }
00376
00377 static comsys_t *get_comsys(dbref which)
00378 {
00379 if (which < 0)
00380 {
00381 return NULL;
00382 }
00383
00384 comsys_t *c = comsys_table[which % NUM_COMSYS];
00385
00386 while (c && (c->who != which))
00387 c = c->next;
00388
00389 if (!c)
00390 {
00391 c = create_new_comsys();
00392 c->who = which;
00393 add_comsys(c);
00394 }
00395 return c;
00396 }
00397
00398 void add_comsys(comsys_t *c)
00399 {
00400 if (c->who < 0 || c->who >= mudstate.db_top)
00401 {
00402 Log.tinyprintf("add_comsys: dbref %d out of range [0, %d)" ENDLINE, c->who, mudstate.db_top);
00403 return;
00404 }
00405
00406 c->next = comsys_table[c->who % NUM_COMSYS];
00407 comsys_table[c->who % NUM_COMSYS] = c;
00408 }
00409
00410 void del_comsys(dbref who)
00411 {
00412 if (who < 0 || who >= mudstate.db_top)
00413 {
00414 Log.tinyprintf("del_comsys: dbref %d out of range [0, %d)" ENDLINE, who, mudstate.db_top);
00415 return;
00416 }
00417
00418 comsys_t *c = comsys_table[who % NUM_COMSYS];
00419
00420 if (c == NULL)
00421 {
00422 return;
00423 }
00424
00425 if (c->who == who)
00426 {
00427 comsys_table[who % NUM_COMSYS] = c->next;
00428 destroy_comsys(c);
00429 return;
00430 }
00431 comsys_t *last = c;
00432 c = c->next;
00433 while (c)
00434 {
00435 if (c->who == who)
00436 {
00437 last->next = c->next;
00438 destroy_comsys(c);
00439 return;
00440 }
00441 last = c;
00442 c = c->next;
00443 }
00444 }
00445
00446 void destroy_comsys(comsys_t *c)
00447 {
00448 int i;
00449
00450 if (c->alias)
00451 {
00452 MEMFREE(c->alias);
00453 c->alias = NULL;
00454 }
00455 for (i = 0; i < c->numchannels; i++)
00456 {
00457 MEMFREE(c->channels[i]);
00458 c->channels[i] = NULL;
00459 }
00460 if (c->channels)
00461 {
00462 MEMFREE(c->channels);
00463 c->channels = NULL;
00464 }
00465 MEMFREE(c);
00466 c = NULL;
00467 }
00468
00469 void sort_com_aliases(comsys_t *c)
00470 {
00471 int i;
00472 char buffer[10];
00473 char *s;
00474 bool cont = true;
00475
00476 while (cont)
00477 {
00478 cont = false;
00479 for (i = 0; i < c->numchannels - 1; i++)
00480 {
00481 if (strcmp(c->alias + i * ALIAS_SIZE, c->alias + (i + 1) * ALIAS_SIZE) > 0)
00482 {
00483 strcpy(buffer, c->alias + i * ALIAS_SIZE);
00484 strcpy(c->alias + i * ALIAS_SIZE, c->alias + (i + 1) * ALIAS_SIZE);
00485 strcpy(c->alias + (i + 1) * ALIAS_SIZE, buffer);
00486 s = c->channels[i];
00487 c->channels[i] = c->channels[i + 1];
00488 c->channels[i + 1] = s;
00489 cont = true;
00490 }
00491 }
00492 }
00493 }
00494
00495 static char *get_channel_from_alias(dbref player, char *alias)
00496 {
00497 int first, last, current, dir;
00498
00499 comsys_t *c = get_comsys(player);
00500
00501 current = first = 0;
00502 last = c->numchannels - 1;
00503 dir = 1;
00504
00505 while (dir && (first <= last))
00506 {
00507 current = (first + last) / 2;
00508 dir = strcmp(alias, c->alias + ALIAS_SIZE * current);
00509 if (dir < 0)
00510 last = current - 1;
00511 else
00512 first = current + 1;
00513 }
00514
00515 if (!dir)
00516 {
00517 return c->channels[current];
00518 }
00519 else
00520 {
00521 return "";
00522 }
00523 }
00524
00525 void load_comsystem(FILE *fp)
00526 {
00527 int i, j, dummy;
00528 int ver = 0;
00529 struct channel *ch;
00530 char temp[LBUF_SIZE];
00531
00532 num_channels = 0;
00533
00534 int nc = 0;
00535 fgets(temp, sizeof(temp), fp);
00536 if (!strncmp(temp, "+V", 2))
00537 {
00538
00539
00540 ver = mux_atol(temp + 2);
00541 if (ver < 1 || 3 < ver)
00542 {
00543 return;
00544 }
00545 int cc;
00546 cc = fscanf(fp, "%d\n", &nc);
00547 mux_assert(1 == cc);
00548 }
00549 else
00550 {
00551 nc = mux_atol(temp);
00552 }
00553
00554 num_channels = nc;
00555
00556 for (i = 0; i < nc; i++)
00557 {
00558 ch = (struct channel *)MEMALLOC(sizeof(struct channel));
00559 ISOUTOFMEMORY(ch);
00560
00561 int nChannel = GetLineTrunc(temp, sizeof(temp), fp);
00562 if (nChannel > MAX_CHANNEL_LEN)
00563 {
00564 nChannel = MAX_CHANNEL_LEN;
00565 }
00566 if (temp[nChannel-1] == '\n')
00567 {
00568
00569
00570 nChannel--;
00571 }
00572 memcpy(ch->name, temp, nChannel);
00573 ch->name[nChannel] = '\0';
00574
00575 if (ver >= 2)
00576 {
00577 int nHeader = GetLineTrunc(temp, sizeof(temp), fp);
00578 if (nHeader > MAX_HEADER_LEN)
00579 {
00580 nHeader = MAX_HEADER_LEN;
00581 }
00582 if (temp[nHeader-1] == '\n')
00583 {
00584 nHeader--;
00585 }
00586 memcpy(ch->header, temp, nHeader);
00587 ch->header[nHeader] = '\0';
00588 }
00589
00590 ch->on_users = NULL;
00591
00592 hashaddLEN(ch->name, nChannel, ch, &mudstate.channel_htab);
00593
00594 ch->type = 127;
00595 ch->temp1 = 0;
00596 ch->temp2 = 0;
00597 ch->charge = 0;
00598 ch->charge_who = NOTHING;
00599 ch->amount_col = 0;
00600 ch->num_messages = 0;
00601 ch->chan_obj = NOTHING;
00602
00603 int cc;
00604 if (ver >= 1)
00605 {
00606 cc = fscanf(fp, "%d %d %d %d %d %d %d %d\n",
00607 &(ch->type), &(ch->temp1), &(ch->temp2),
00608 &(ch->charge), &(ch->charge_who),
00609 &(ch->amount_col), &(ch->num_messages), &(ch->chan_obj));
00610 mux_assert(8 == cc);
00611 }
00612 else
00613 {
00614 cc = fscanf(fp, "%d %d %d %d %d %d %d %d %d %d\n",
00615 &(ch->type), &(dummy), &(ch->temp1), &(ch->temp2),
00616 &(dummy), &(ch->charge), &(ch->charge_who),
00617 &(ch->amount_col), &(ch->num_messages), &(ch->chan_obj));
00618 mux_assert(10 == cc);
00619 }
00620
00621 if (ver <= 1)
00622 {
00623
00624
00625 if (ch->type & CHANNEL_PUBLIC)
00626 {
00627 sprintf(temp, "%s[%s%s%s%s%s]%s", ANSI_CYAN, ANSI_HILITE,
00628 ANSI_BLUE, ch->name, ANSI_NORMAL, ANSI_CYAN, ANSI_NORMAL);
00629 }
00630 else
00631 {
00632 sprintf(temp, "%s[%s%s%s%s%s]%s", ANSI_MAGENTA, ANSI_HILITE,
00633 ANSI_RED, ch->name, ANSI_NORMAL, ANSI_MAGENTA,
00634 ANSI_NORMAL);
00635 }
00636 int vwVisual;
00637 ANSI_TruncateToField(temp, MAX_HEADER_LEN+1, ch->header,
00638 MAX_HEADER_LEN+1, &vwVisual, ANSI_ENDGOAL_NORMAL);
00639 }
00640
00641 ch->num_users = 0;
00642 cc =fscanf(fp, "%d\n", &(ch->num_users));
00643 mux_assert(1 == cc);
00644 ch->max_users = ch->num_users;
00645 if (ch->num_users > 0)
00646 {
00647 ch->users = (struct comuser **)calloc(ch->max_users, sizeof(struct comuser *));
00648 ISOUTOFMEMORY(ch->users);
00649
00650 int jAdded = 0;
00651 for (j = 0; j < ch->num_users; j++)
00652 {
00653 struct comuser t_user;
00654 memset(&t_user, 0, sizeof(t_user));
00655
00656 t_user.who = NOTHING;
00657 t_user.bUserIsOn = false;
00658 t_user.ComTitleStatus = false;
00659
00660 int iUserIsOn;
00661 if (ver == 3)
00662 {
00663 int iComTitleStatus;
00664 cc = fscanf(fp, "%d %d %d\n", &(t_user.who), &iUserIsOn,
00665 &iComTitleStatus);
00666 mux_assert(3 == cc);
00667 t_user.bUserIsOn = (iUserIsOn ? true : false);
00668 t_user.ComTitleStatus = (iComTitleStatus ? true : false);
00669 }
00670 else
00671 {
00672 t_user.ComTitleStatus = true;
00673 if (ver)
00674 {
00675 cc = fscanf(fp, "%d %d\n", &(t_user.who), &iUserIsOn);
00676 mux_assert(2 == cc);
00677 t_user.bUserIsOn = (iUserIsOn ? true : false);
00678 }
00679 else
00680 {
00681 cc = fscanf(fp, "%d %d %d", &(t_user.who), &(dummy), &(dummy));
00682 mux_assert(3 == cc);
00683 cc = fscanf(fp, "%d\n", &iUserIsOn);
00684 mux_assert(1 == cc);
00685 t_user.bUserIsOn = (iUserIsOn ? true : false);
00686 }
00687 }
00688
00689
00690
00691 int nTitle = GetLineTrunc(temp, sizeof(temp), fp);
00692 char *pTitle = temp;
00693
00694 if (!Good_dbref(t_user.who))
00695 {
00696 Log.tinyprintf("load_comsystem: dbref %d out of range [0, %d)." ENDLINE, t_user.who, mudstate.db_top);
00697 }
00698 else if (isGarbage(t_user.who))
00699 {
00700 Log.tinyprintf("load_comsystem: dbref is GARBAGE." ENDLINE, t_user.who);
00701 }
00702 else
00703 {
00704
00705
00706 if (3 < nTitle && temp[0] == 't' && temp[1] == ':')
00707 {
00708 pTitle = temp+2;
00709 nTitle -= 2;
00710 if (pTitle[nTitle-1] == '\n')
00711 {
00712
00713
00714 nTitle--;
00715 }
00716 if (nTitle <= 0 || MAX_TITLE_LEN < nTitle)
00717 {
00718 nTitle = 0;
00719 pTitle = temp;
00720 }
00721 }
00722 else
00723 {
00724 nTitle = 0;
00725 }
00726
00727 struct comuser *user = (struct comuser *)MEMALLOC(sizeof(struct comuser));
00728 ISOUTOFMEMORY(user);
00729 memcpy(user, &t_user, sizeof(struct comuser));
00730
00731 user->title = StringCloneLen(pTitle, nTitle);
00732 ch->users[jAdded++] = user;
00733
00734 if ( !(isPlayer(user->who))
00735 && !(Going(user->who)
00736 && (God(Owner(user->who)))))
00737 {
00738 do_joinchannel(user->who, ch);
00739 }
00740 user->on_next = ch->on_users;
00741 ch->on_users = user;
00742 }
00743 }
00744 ch->num_users = jAdded;
00745 sort_users(ch);
00746 }
00747 else
00748 {
00749 ch->users = NULL;
00750 }
00751 }
00752 }
00753
00754 void save_comsystem(FILE *fp)
00755 {
00756 struct channel *ch;
00757 struct comuser *user;
00758 int j;
00759
00760 fprintf(fp, "+V3\n");
00761 fprintf(fp, "%d\n", num_channels);
00762 for (ch = (struct channel *)hash_firstentry(&mudstate.channel_htab);
00763 ch;
00764 ch = (struct channel *)hash_nextentry(&mudstate.channel_htab))
00765 {
00766 fprintf(fp, "%s\n", ch->name);
00767 fprintf(fp, "%s\n", ch->header);
00768
00769 fprintf(fp, "%d %d %d %d %d %d %d %d\n", ch->type, ch->temp1,
00770 ch->temp2, ch->charge, ch->charge_who, ch->amount_col,
00771 ch->num_messages, ch->chan_obj);
00772
00773
00774
00775 int nUsers = 0;
00776 for (j = 0; j < ch->num_users; j++)
00777 {
00778 user = ch->users[j];
00779 if (user->who >= 0 && user->who < mudstate.db_top)
00780 {
00781 nUsers++;
00782 }
00783 }
00784
00785 fprintf(fp, "%d\n", nUsers);
00786 for (j = 0; j < ch->num_users; j++)
00787 {
00788 user = ch->users[j];
00789 if (user->who >= 0 && user->who < mudstate.db_top)
00790 {
00791 user = ch->users[j];
00792 fprintf(fp, "%d %d %d\n", user->who, user->bUserIsOn, user->ComTitleStatus);
00793 if (user->title[0] != '\0')
00794 {
00795 fprintf(fp, "t:%s\n", user->title);
00796 }
00797 else
00798 {
00799 fprintf(fp, "t:\n");
00800 }
00801 }
00802 }
00803 }
00804 }
00805
00806 static void BuildChannelMessage
00807 (
00808 bool bSpoof,
00809 const char *pHeader,
00810 struct comuser *user,
00811 char *pPose,
00812 char **messNormal,
00813 char **messNoComtitle
00814 )
00815 {
00816
00817
00818 *messNormal = alloc_lbuf("BCM.messNormal");
00819 *messNoComtitle = NULL;
00820 if (!bSpoof)
00821 {
00822 *messNoComtitle = alloc_lbuf("BCM.messNoComtitle");
00823 }
00824
00825
00826
00827 bool hasComTitle = (user->title[0] != '\0');
00828
00829 char *mnptr = *messNormal;
00830 char *mncptr = *messNoComtitle;
00831
00832 safe_str(pHeader, *messNormal, &mnptr);
00833 safe_chr(' ', *messNormal, &mnptr);
00834 if (!bSpoof)
00835 {
00836 safe_str(pHeader, *messNoComtitle, &mncptr);
00837 safe_chr(' ', *messNoComtitle, &mncptr);
00838 }
00839
00840
00841
00842
00843 if (hasComTitle && (user->ComTitleStatus || bSpoof))
00844 {
00845 if (mudconf.eval_comtitle)
00846 {
00847
00848
00849 char TempToEval[LBUF_SIZE];
00850 strcpy(TempToEval, user->title);
00851 char *q = TempToEval;
00852 mux_exec(*messNormal, &mnptr, user->who, user->who, user->who,
00853 EV_FCHECK | EV_EVAL | EV_TOP, &q, (char **)NULL, 0);
00854 }
00855 else
00856 {
00857 safe_str(user->title, *messNormal, &mnptr);
00858 }
00859 if (!bSpoof)
00860 {
00861 safe_chr(' ', *messNormal, &mnptr);
00862 safe_str(Moniker(user->who), *messNormal, &mnptr);
00863 safe_str(Moniker(user->who), *messNoComtitle, &mncptr);
00864 }
00865 }
00866 else
00867 {
00868 safe_str(Moniker(user->who), *messNormal, &mnptr);
00869 if (!bSpoof)
00870 {
00871 safe_str(Moniker(user->who), *messNoComtitle, &mncptr);
00872 }
00873 }
00874
00875 char *saystring = NULL;
00876 char *newPose = NULL;
00877
00878 switch(pPose[0])
00879 {
00880 case ':':
00881 pPose++;
00882 newPose = modSpeech(user->who, pPose, true, "channel/pose");
00883 if (newPose)
00884 {
00885 pPose = newPose;
00886 }
00887 safe_chr(' ', *messNormal, &mnptr);
00888 safe_str(pPose, *messNormal, &mnptr);
00889 if (!bSpoof)
00890 {
00891 safe_chr(' ', *messNoComtitle, &mncptr);
00892 safe_str(pPose, *messNoComtitle, &mncptr);
00893 }
00894 break;
00895
00896 case ';':
00897 pPose++;
00898 newPose = modSpeech(user->who, pPose, true, "channel/pose");
00899 if (newPose)
00900 {
00901 pPose = newPose;
00902 }
00903 safe_str(pPose, *messNormal, &mnptr);
00904 if (!bSpoof)
00905 {
00906 safe_str(pPose, *messNoComtitle, &mncptr);
00907 }
00908 break;
00909
00910 default:
00911 newPose = modSpeech(user->who, pPose, true, "channel");
00912 if (newPose)
00913 {
00914 pPose = newPose;
00915 }
00916 saystring = modSpeech(user->who, pPose, false, "channel");
00917 if (saystring)
00918 {
00919 safe_chr(' ', *messNormal, &mnptr);
00920 safe_str(saystring, *messNormal, &mnptr);
00921 safe_str(" \"", *messNormal, &mnptr);
00922 }
00923 else
00924 {
00925 safe_str(" says, \"", *messNormal, &mnptr);
00926 }
00927 safe_str(pPose, *messNormal, &mnptr);
00928 safe_chr('"', *messNormal, &mnptr);
00929 if (!bSpoof)
00930 {
00931 if (saystring)
00932 {
00933 safe_chr(' ', *messNoComtitle, &mncptr);
00934 safe_str(saystring, *messNoComtitle, &mncptr);
00935 safe_str(" \"", *messNoComtitle, &mncptr);
00936 }
00937 else
00938 {
00939 safe_str(" says, \"", *messNoComtitle, &mncptr);
00940 }
00941 safe_str(pPose, *messNoComtitle, &mncptr);
00942 safe_chr('"', *messNoComtitle, &mncptr);
00943 }
00944 break;
00945 }
00946 *mnptr = '\0';
00947 if (!bSpoof)
00948 {
00949 *mncptr = '\0';
00950 }
00951 if (newPose)
00952 {
00953 free_lbuf(newPose);
00954 }
00955 if (saystring)
00956 {
00957 free_lbuf(saystring);
00958 }
00959 }
00960
00961 static void do_processcom(dbref player, char *arg1, char *arg2)
00962 {
00963 if (!*arg2)
00964 {
00965 raw_notify(player, "No message.");
00966 return;
00967 }
00968 if (3500 < strlen(arg2))
00969 {
00970 arg2[3500] = '\0';
00971 }
00972 struct channel *ch = select_channel(arg1);
00973 if (!ch)
00974 {
00975 raw_notify(player, tprintf("Unknown channel %s.", arg1));
00976 return;
00977 }
00978 struct comuser *user = select_user(ch, player);
00979 if (!user)
00980 {
00981 raw_notify(player, "You are not listed as on that channel. Delete this alias and readd.");
00982 return;
00983 }
00984 if ( Gagged(player)
00985 && !Wizard(player))
00986 {
00987 raw_notify(player, "GAGGED players may not speak on channels.");
00988 return;
00989 }
00990 if (!strcmp(arg2, "on"))
00991 {
00992 do_joinchannel(player, ch);
00993 }
00994 else if (!strcmp(arg2, "off"))
00995 {
00996 do_leavechannel(player, ch);
00997 }
00998 else if (!user->bUserIsOn)
00999 {
01000 raw_notify(player, tprintf("You must be on %s to do that.", arg1));
01001 return;
01002 }
01003 else if (!strcmp(arg2, "who"))
01004 {
01005 do_comwho(player, ch);
01006 }
01007 else if ( !strncmp(arg2, "last", 4)
01008 && ( arg2[4] == '\0'
01009 || ( arg2[4] == ' '
01010 && is_integer(arg2 + 5, NULL))))
01011 {
01012
01013
01014 int nRecall = DFLT_RECALL_REQUEST;
01015 if (arg2[4] == ' ')
01016 {
01017 nRecall = mux_atol(arg2 + 5);
01018 }
01019 do_comlast(player, ch, nRecall);
01020 }
01021 else if (!test_transmit_access(player, ch))
01022 {
01023 raw_notify(player, "That channel type cannot be transmitted on.");
01024 return;
01025 }
01026 else
01027 {
01028 if (!payfor(player, Guest(player) ? 0 : ch->charge))
01029 {
01030 notify(player, tprintf("You don't have enough %s.", mudconf.many_coins));
01031 return;
01032 }
01033 else
01034 {
01035 ch->amount_col += ch->charge;
01036 giveto(ch->charge_who, ch->charge);
01037 }
01038
01039
01040
01041
01042 char *messNormal;
01043 char *messNoComtitle;
01044 BuildChannelMessage((ch->type & CHANNEL_SPOOF) != 0, ch->header, user,
01045 arg2, &messNormal, &messNoComtitle);
01046 SendChannelMessage(player, ch, messNormal, messNoComtitle);
01047 }
01048 }
01049
01050 void SendChannelMessage
01051 (
01052 dbref executor,
01053 struct channel *ch,
01054 char *msgNormal,
01055 char *msgNoComtitle
01056 )
01057 {
01058 bool bSpoof = ((ch->type & CHANNEL_SPOOF) != 0);
01059 ch->num_messages++;
01060
01061 struct comuser *user;
01062 for (user = ch->on_users; user; user = user->on_next)
01063 {
01064 if ( user->bUserIsOn
01065 && test_receive_access(user->who, ch))
01066 {
01067 if ( user->ComTitleStatus
01068 || bSpoof
01069 || msgNoComtitle == NULL)
01070 {
01071 notify_with_cause_ooc(user->who, executor, msgNormal);
01072 }
01073 else
01074 {
01075 notify_with_cause_ooc(user->who, executor, msgNoComtitle);
01076 }
01077 }
01078 }
01079
01080 dbref obj = ch->chan_obj;
01081 if (Good_obj(obj))
01082 {
01083 dbref aowner;
01084 int aflags;
01085 int logmax = DFLT_MAX_LOG;
01086 char *maxbuf;
01087 ATTR *pattr = atr_str("MAX_LOG");
01088 if ( pattr
01089 && pattr->number)
01090 {
01091 maxbuf = atr_get(obj, pattr->number, &aowner, &aflags);
01092 logmax = mux_atol(maxbuf);
01093 free_lbuf(maxbuf);
01094 }
01095 if (logmax > 0)
01096 {
01097 if (logmax > MAX_RECALL_REQUEST)
01098 {
01099 logmax = MAX_RECALL_REQUEST;
01100 atr_add(ch->chan_obj, pattr->number, mux_ltoa_t(logmax), GOD,
01101 AF_CONST|AF_NOPROG|AF_NOPARSE);
01102 }
01103 char *p = tprintf("HISTORY_%d", iMod(ch->num_messages, logmax));
01104 int atr = mkattr(GOD, p);
01105 if (0 < atr)
01106 {
01107 atr_add(ch->chan_obj, atr, msgNormal, GOD, AF_CONST|AF_NOPROG|AF_NOPARSE);
01108 }
01109 }
01110 }
01111 else if (ch->chan_obj != NOTHING)
01112 {
01113 ch->chan_obj = NOTHING;
01114 }
01115
01116
01117
01118 if (msgNormal)
01119 {
01120 free_lbuf(msgNormal);
01121 }
01122 if ( msgNoComtitle
01123 && msgNoComtitle != msgNormal)
01124 {
01125 free_lbuf(msgNoComtitle);
01126 }
01127 }
01128
01129 void do_joinchannel(dbref player, struct channel *ch)
01130 {
01131 struct comuser **cu;
01132 int i;
01133
01134 struct comuser *user = select_user(ch, player);
01135
01136 if (!user)
01137 {
01138 ch->num_users++;
01139 if (ch->num_users >= ch->max_users)
01140 {
01141 ch->max_users += 10;
01142 cu = (struct comuser **)MEMALLOC(sizeof(struct comuser *) * ch->max_users);
01143 ISOUTOFMEMORY(cu);
01144
01145 for (i = 0; i < (ch->num_users - 1); i++)
01146 {
01147 cu[i] = ch->users[i];
01148 }
01149 MEMFREE(ch->users);
01150 ch->users = cu;
01151 }
01152 user = (struct comuser *)MEMALLOC(sizeof(struct comuser));
01153 ISOUTOFMEMORY(user);
01154
01155 for (i = ch->num_users - 1; i > 0 && ch->users[i - 1]->who > player; i--)
01156 {
01157 ch->users[i] = ch->users[i - 1];
01158 }
01159 ch->users[i] = user;
01160
01161 user->who = player;
01162 user->bUserIsOn = true;
01163 user->ComTitleStatus = true;
01164 user->title = StringClone("");
01165
01166
01167
01168 if (UNDEAD(player))
01169 {
01170 user->on_next = ch->on_users;
01171 ch->on_users = user;
01172 }
01173 }
01174 else if (!user->bUserIsOn)
01175 {
01176 user->bUserIsOn = true;
01177 }
01178 else
01179 {
01180 raw_notify(player, tprintf("You are already on channel %s.", ch->name));
01181 return;
01182 }
01183
01184 if (!Hidden(player))
01185 {
01186 char *messNormal, *messNoComtitle;
01187 BuildChannelMessage((ch->type & CHANNEL_SPOOF) != 0, ch->header, user,
01188 ":has joined this channel.", &messNormal, &messNoComtitle);
01189 SendChannelMessage(player, ch, messNormal, messNoComtitle);
01190 }
01191 }
01192
01193 void do_leavechannel(dbref player, struct channel *ch)
01194 {
01195 struct comuser *user = select_user(ch, player);
01196 raw_notify(player, tprintf("You have left channel %s.", ch->name));
01197 if ( user->bUserIsOn
01198 && !Hidden(player))
01199 {
01200 char *messNormal, *messNoComtitle;
01201 BuildChannelMessage((ch->type & CHANNEL_SPOOF) != 0, ch->header, user,
01202 ":has left this channel.", &messNormal, &messNoComtitle);
01203 SendChannelMessage(player, ch, messNormal, messNoComtitle);
01204 }
01205 user->bUserIsOn = false;
01206 }
01207
01208 static void do_comwho_line
01209 (
01210 dbref player,
01211 struct channel *ch,
01212 struct comuser *user
01213 )
01214 {
01215 char *msg;
01216 char *buff = NULL;
01217
01218 if (user->title[0] != '\0')
01219 {
01220
01221
01222 if (Staff(player))
01223 {
01224 buff = unparse_object(player, user->who, false);
01225 if (ch->type & CHANNEL_SPOOF)
01226 {
01227 msg = tprintf("%s as %s", buff, user->title);
01228 }
01229 else
01230 {
01231 msg = tprintf("%s as %s %s", buff, user->title, buff);
01232 }
01233 }
01234 else
01235 {
01236 if (ch->type & CHANNEL_SPOOF)
01237 {
01238 msg = user->title;
01239 }
01240 else
01241 {
01242 buff = unparse_object(player, user->who, false);
01243 msg = tprintf("%s %s", user->title, buff);
01244 }
01245 }
01246 }
01247 else
01248 {
01249 buff = unparse_object(player, user->who, false);
01250 msg = buff;
01251 }
01252
01253 raw_notify(player, msg);
01254 if (buff)
01255 {
01256 free_lbuf(buff);
01257 }
01258 }
01259
01260 void do_comwho(dbref player, struct channel *ch)
01261 {
01262 struct comuser *user;
01263
01264 raw_notify(player, "-- Players --");
01265 for (user = ch->on_users; user; user = user->on_next)
01266 {
01267 if (isPlayer(user->who))
01268 {
01269 if ( Connected(user->who)
01270 && ( !Hidden(user->who)
01271 || Wizard_Who(player)
01272 || See_Hidden(player)))
01273 {
01274 if (user->bUserIsOn)
01275 {
01276 do_comwho_line(player, ch, user);
01277 }
01278 }
01279 else if (!Hidden(user->who))
01280 {
01281 do_comdisconnectchannel(user->who, ch->name);
01282 }
01283 }
01284 }
01285 raw_notify(player, "-- Objects --");
01286 for (user = ch->on_users; user; user = user->on_next)
01287 {
01288 if (!isPlayer(user->who))
01289 {
01290 if ( Going(user->who)
01291 && God(Owner(user->who)))
01292 {
01293 do_comdisconnectchannel(user->who, ch->name);
01294 }
01295 else if (user->bUserIsOn)
01296 {
01297 do_comwho_line(player, ch, user);
01298 }
01299 }
01300 }
01301 raw_notify(player, tprintf("-- %s --", ch->name));
01302 }
01303
01304 void do_comlast(dbref player, struct channel *ch, int arg)
01305 {
01306 if (!Good_obj(ch->chan_obj))
01307 {
01308 raw_notify(player, "Channel does not have an object.");
01309 return;
01310 }
01311 dbref aowner;
01312 int aflags;
01313 dbref obj = ch->chan_obj;
01314 int logmax = MAX_RECALL_REQUEST;
01315 ATTR *pattr = atr_str("MAX_LOG");
01316 if ( pattr
01317 && (atr_get_info(obj, pattr->number, &aowner, &aflags)))
01318 {
01319 char *maxbuf = atr_get(obj, pattr->number, &aowner, &aflags);
01320 logmax = mux_atol(maxbuf);
01321 free_lbuf(maxbuf);
01322 }
01323 if (logmax < 1)
01324 {
01325 raw_notify(player, "Channel does not log.");
01326 return;
01327 }
01328 if (arg < MIN_RECALL_REQUEST)
01329 {
01330 arg = MIN_RECALL_REQUEST;
01331 }
01332 if (arg > logmax)
01333 {
01334 arg = logmax;
01335 }
01336
01337 char *message;
01338 int histnum = ch->num_messages - arg;
01339
01340 raw_notify(player, "-- Begin Comsys Recall --");
01341 for (int count = 0; count < arg; count++)
01342 {
01343 histnum++;
01344 pattr = atr_str(tprintf("HISTORY_%d", iMod(histnum, logmax)));
01345 if (pattr)
01346 {
01347 message = atr_get(obj, pattr->number, &aowner, &aflags);
01348 raw_notify(player, message);
01349 free_lbuf(message);
01350 }
01351 }
01352 raw_notify(player, "-- End Comsys Recall --");
01353 }
01354
01355 static bool do_chanlog(dbref player, char *channel, char *arg)
01356 {
01357 UNUSED_PARAMETER(player);
01358
01359 int value;
01360 if ( !*arg
01361 || !is_integer(arg, NULL)
01362 || (value = mux_atol(arg)) > MAX_RECALL_REQUEST)
01363 {
01364 return false;
01365 }
01366 if (value < 0)
01367 {
01368 value = 0;
01369 }
01370 struct channel *ch = select_channel(channel);
01371 if (!Good_obj(ch->chan_obj))
01372 {
01373
01374
01375 return false;
01376 }
01377 int atr = mkattr(GOD, "MAX_LOG");
01378 if (atr <= 0)
01379 {
01380 return false;
01381 }
01382 dbref aowner;
01383 int aflags;
01384 char *oldvalue = atr_get(ch->chan_obj, atr, &aowner, &aflags);
01385 if (oldvalue)
01386 {
01387 int oldnum = mux_atol(oldvalue);
01388 if (oldnum > value)
01389 {
01390 ATTR *hist;
01391 for (int count = 0; count <= oldnum; count++)
01392 {
01393 hist = atr_str(tprintf("HISTORY_%d", count));
01394 if (hist)
01395 {
01396 atr_clr(ch->chan_obj, hist->number);
01397 }
01398 }
01399 }
01400 free_lbuf(oldvalue);
01401 }
01402 atr_add(ch->chan_obj, atr, mux_ltoa_t(value), GOD,
01403 AF_CONST|AF_NOPROG|AF_NOPARSE);
01404 return true;
01405 }
01406
01407 struct channel *select_channel(char *channel)
01408 {
01409 struct channel *cp = (struct channel *)hashfindLEN(channel,
01410 strlen(channel), &mudstate.channel_htab);
01411 return cp;
01412 }
01413
01414 struct comuser *select_user(struct channel *ch, dbref player)
01415 {
01416 if (!ch)
01417 {
01418 return NULL;
01419 }
01420
01421 int first = 0;
01422 int last = ch->num_users - 1;
01423 int dir = 1;
01424 int current = 0;
01425
01426 while (dir && (first <= last))
01427 {
01428 current = (first + last) / 2;
01429 if (ch->users[current] == NULL)
01430 {
01431 last--;
01432 continue;
01433 }
01434 if (ch->users[current]->who == player)
01435 {
01436 dir = 0;
01437 }
01438 else if (ch->users[current]->who < player)
01439 {
01440 dir = 1;
01441 first = current + 1;
01442 }
01443 else
01444 {
01445 dir = -1;
01446 last = current - 1;
01447 }
01448 }
01449
01450 if (!dir)
01451 {
01452 return ch->users[current];
01453 }
01454 else
01455 {
01456 return NULL;
01457 }
01458 }
01459
01460 #define MAX_ALIASES_PER_PLAYER 50
01461
01462 void do_addcom
01463 (
01464 dbref executor,
01465 dbref caller,
01466 dbref enactor,
01467 int key,
01468 int nargs,
01469 char *arg1,
01470 char *arg2
01471 )
01472 {
01473 UNUSED_PARAMETER(caller);
01474 UNUSED_PARAMETER(enactor);
01475 UNUSED_PARAMETER(key);
01476 UNUSED_PARAMETER(nargs);
01477
01478 if (!mudconf.have_comsys)
01479 {
01480 raw_notify(executor, "Comsys disabled.");
01481 return;
01482 }
01483 bool bValidAlias;
01484 int nValidAlias;
01485 char *pValidAlias = MakeCanonicalComAlias(arg1, &nValidAlias, &bValidAlias);
01486 if (!bValidAlias)
01487 {
01488 raw_notify(executor, "You need to specify a valid alias.");
01489 return;
01490 }
01491 char *s = arg2;
01492 if (!*s)
01493 {
01494 raw_notify(executor, "You need to specify a channel.");
01495 return;
01496 }
01497 char channel[MAX_CHANNEL_LEN+1];
01498 char *t = channel;
01499 while (*s && ((t - channel) < MAX_CHANNEL_LEN))
01500 {
01501 if (*s != ' ')
01502 *t++ = *s++;
01503 else
01504 s++;
01505 }
01506 *t = '\0';
01507
01508 int i, j, where;
01509 char *na;
01510 char **nc;
01511 struct channel *ch = select_channel(channel);
01512 char Buffer[MAX_CHANNEL_LEN+1];
01513 if (!ch)
01514 {
01515 int nVisualWidth;
01516 ANSI_TruncateToField(channel, sizeof(Buffer), Buffer, sizeof(Buffer), &nVisualWidth, ANSI_ENDGOAL_NORMAL);
01517 raw_notify(executor, tprintf("Channel %s does not exist yet.", Buffer));
01518 return;
01519 }
01520 if (!test_join_access(executor, ch))
01521 {
01522 raw_notify(executor, "Sorry, this channel type does not allow you to join.");
01523 return;
01524 }
01525 comsys_t *c = get_comsys(executor);
01526 if (c->numchannels >= MAX_ALIASES_PER_PLAYER)
01527 {
01528 raw_notify(executor, tprintf("Sorry, but you have reached the maximum number of aliases allowed."));
01529 return;
01530 }
01531 for (j = 0; j < c->numchannels && (strcmp(pValidAlias, c->alias + j * ALIAS_SIZE) > 0); j++)
01532 {
01533 ;
01534 }
01535 if (j < c->numchannels && !strcmp(pValidAlias, c->alias + j * ALIAS_SIZE))
01536 {
01537 char *p = tprintf("That alias is already in use for channel %s.", c->channels[j]);
01538 raw_notify(executor, p);
01539 return;
01540 }
01541 if (c->numchannels >= c->maxchannels)
01542 {
01543 c->maxchannels += 10;
01544
01545 na = (char *)MEMALLOC(ALIAS_SIZE * c->maxchannels);
01546 ISOUTOFMEMORY(na);
01547 nc = (char **)MEMALLOC(sizeof(char *) * c->maxchannels);
01548 ISOUTOFMEMORY(nc);
01549
01550 for (i = 0; i < c->numchannels; i++)
01551 {
01552 strcpy(na + i * ALIAS_SIZE, c->alias + i * ALIAS_SIZE);
01553 nc[i] = c->channels[i];
01554 }
01555 if (c->alias)
01556 {
01557 MEMFREE(c->alias);
01558 c->alias = NULL;
01559 }
01560 if (c->channels)
01561 {
01562 MEMFREE(c->channels);
01563 c->channels = NULL;
01564 }
01565 c->alias = na;
01566 c->channels = nc;
01567 }
01568 where = c->numchannels++;
01569 for (i = where; i > j; i--)
01570 {
01571 strcpy(c->alias + i * ALIAS_SIZE, c->alias + (i - 1) * ALIAS_SIZE);
01572 c->channels[i] = c->channels[i - 1];
01573 }
01574
01575 where = j;
01576 memcpy(c->alias + where * ALIAS_SIZE, pValidAlias, nValidAlias);
01577 *(c->alias + where * ALIAS_SIZE + nValidAlias) = '\0';
01578 c->channels[where] = StringClone(channel);
01579
01580 if (!select_user(ch, executor))
01581 {
01582 do_joinchannel(executor, ch);
01583 }
01584
01585 raw_notify(executor, tprintf("Channel %s added with alias %s.", channel, pValidAlias));
01586 }
01587
01588 void do_delcom(dbref executor, dbref caller, dbref enactor, int key, char *arg1)
01589 {
01590 UNUSED_PARAMETER(caller);
01591 UNUSED_PARAMETER(enactor);
01592 UNUSED_PARAMETER(key);
01593
01594 if (!mudconf.have_comsys)
01595 {
01596 raw_notify(executor, "Comsys disabled.");
01597 return;
01598 }
01599 if (!arg1)
01600 {
01601 raw_notify(executor, "Need an alias to delete.");
01602 return;
01603 }
01604 comsys_t *c = get_comsys(executor);
01605 int i;
01606
01607 for (i = 0; i < c->numchannels; i++)
01608 {
01609 if (!strcmp(arg1, c->alias + i * ALIAS_SIZE))
01610 {
01611 int itmp, found = 0;
01612 for (itmp = 0;itmp < c->numchannels; itmp++)
01613 {
01614 if (!strcmp(c->channels[itmp],c->channels[i]))
01615 {
01616 found++;
01617 }
01618 }
01619
01620
01621
01622 if (found <= 1)
01623 {
01624 do_delcomchannel(executor, c->channels[i], false);
01625 raw_notify(executor, tprintf("Alias %s for channel %s deleted.",
01626 arg1, c->channels[i]));
01627 MEMFREE(c->channels[i]);
01628 }
01629 else
01630 {
01631 raw_notify(executor, tprintf("Alias %s for channel %s deleted.",
01632 arg1, c->channels[i]));
01633 }
01634
01635 c->channels[i] = NULL;
01636 c->numchannels--;
01637
01638 for (; i < c->numchannels; i++)
01639 {
01640 strcpy(c->alias + i * ALIAS_SIZE, c->alias + (i + 1) * ALIAS_SIZE);
01641 c->channels[i] = c->channels[i + 1];
01642 }
01643 return;
01644 }
01645 }
01646 raw_notify(executor, "Unable to find that alias.");
01647 }
01648
01649 void do_delcomchannel(dbref player, char *channel, bool bQuiet)
01650 {
01651 struct comuser *user;
01652
01653 struct channel *ch = select_channel(channel);
01654 if (!ch)
01655 {
01656 raw_notify(player, tprintf("Unknown channel %s.", channel));
01657 }
01658 else
01659 {
01660 int i;
01661 int j = 0;
01662 for (i = 0; i < ch->num_users && !j; i++)
01663 {
01664 user = ch->users[i];
01665 if (user->who == player)
01666 {
01667 do_comdisconnectchannel(player, channel);
01668 if (!bQuiet)
01669 {
01670 if ( user->bUserIsOn
01671 && !Hidden(player))
01672 {
01673 char *messNormal, *messNoComtitle;
01674 BuildChannelMessage((ch->type & CHANNEL_SPOOF) != 0,
01675 ch->header, user, ":has left this channel.",
01676 &messNormal, &messNoComtitle);
01677 SendChannelMessage(player, ch, messNormal, messNoComtitle);
01678 }
01679 raw_notify(player, tprintf("You have left channel %s.", channel));
01680 }
01681
01682 if (user->title)
01683 {
01684 MEMFREE(user->title);
01685 user->title = NULL;
01686 }
01687 MEMFREE(user);
01688 user = NULL;
01689 j = 1;
01690 }
01691 }
01692
01693 if (j)
01694 {
01695 ch->num_users--;
01696 for (i--; i < ch->num_users; i++)
01697 {
01698 ch->users[i] = ch->users[i + 1];
01699 }
01700 }
01701 }
01702 }
01703
01704 void do_createchannel(dbref executor, dbref caller, dbref enactor, int key, char *channel)
01705 {
01706 UNUSED_PARAMETER(caller);
01707 UNUSED_PARAMETER(enactor);
01708 UNUSED_PARAMETER(key);
01709
01710 if (!*channel)
01711 {
01712 raw_notify(executor, "You must specify a channel to create.");
01713 return;
01714 }
01715 if (!Comm_All(executor))
01716 {
01717 raw_notify(executor, NOPERM_MESSAGE);
01718 return;
01719 }
01720 struct channel *newchannel = (struct channel *)MEMALLOC(sizeof(struct channel));
01721 ISOUTOFMEMORY(newchannel);
01722
01723 int vwChannel;
01724 size_t nNameNoANSI;
01725 char *pNameNoANSI;
01726 char Buffer[MAX_HEADER_LEN];
01727 int nChannel = ANSI_TruncateToField(channel, sizeof(Buffer),
01728 Buffer, sizeof(Buffer), &vwChannel, ANSI_ENDGOAL_NORMAL);
01729 if (nChannel == vwChannel)
01730 {
01731
01732
01733
01734 const int nMax = MAX_HEADER_LEN - (sizeof(ANSI_HILITE)-1)
01735 - (sizeof(ANSI_NORMAL)-1) - 2;
01736 if (nChannel > nMax)
01737 {
01738 nChannel = nMax;
01739 }
01740 Buffer[nChannel] = '\0';
01741 sprintf(newchannel->header, "%s[%s]%s", ANSI_HILITE, Buffer,
01742 ANSI_NORMAL);
01743
01744
01745
01746 nNameNoANSI = nChannel;
01747 pNameNoANSI = Buffer;
01748 }
01749 else
01750 {
01751
01752
01753 memcpy(newchannel->header, Buffer, nChannel+1);
01754 pNameNoANSI = strip_ansi(Buffer, &nNameNoANSI);
01755 }
01756 if (nNameNoANSI > MAX_CHANNEL_LEN)
01757 {
01758 nNameNoANSI = MAX_CHANNEL_LEN;
01759 }
01760 memcpy(newchannel->name, pNameNoANSI, nNameNoANSI);
01761 newchannel->name[nNameNoANSI] = '\0';
01762
01763 if (select_channel(newchannel->name))
01764 {
01765 raw_notify(executor, tprintf("Channel %s already exists.", newchannel->name));
01766 MEMFREE(newchannel);
01767 return;
01768 }
01769
01770 newchannel->type = 127;
01771 newchannel->temp1 = 0;
01772 newchannel->temp2 = 0;
01773 newchannel->charge = 0;
01774 newchannel->charge_who = executor;
01775 newchannel->amount_col = 0;
01776 newchannel->num_users = 0;
01777 newchannel->max_users = 0;
01778 newchannel->users = NULL;
01779 newchannel->on_users = NULL;
01780 newchannel->chan_obj = NOTHING;
01781 newchannel->num_messages = 0;
01782
01783 num_channels++;
01784
01785 hashaddLEN(newchannel->name, strlen(newchannel->name), newchannel, &mudstate.channel_htab);
01786
01787
01788
01789 raw_notify(executor, tprintf("Channel %s created.", newchannel->name));
01790 }
01791
01792 void do_destroychannel(dbref executor, dbref caller, dbref enactor, int key, char *channel)
01793 {
01794 UNUSED_PARAMETER(caller);
01795 UNUSED_PARAMETER(enactor);
01796 UNUSED_PARAMETER(key);
01797
01798 struct channel *ch;
01799 int j;
01800
01801 if (!mudconf.have_comsys)
01802 {
01803 raw_notify(executor, "Comsys disabled.");
01804 return;
01805 }
01806 ch = (struct channel *)hashfindLEN(channel, strlen(channel), &mudstate.channel_htab);
01807
01808 if (!ch)
01809 {
01810 raw_notify(executor, tprintf("Could not find channel %s.", channel));
01811 return;
01812 }
01813 else if ( !Comm_All(executor)
01814 && !Controls(executor, ch->charge_who))
01815 {
01816 raw_notify(executor, NOPERM_MESSAGE);
01817 return;
01818 }
01819 num_channels--;
01820 hashdeleteLEN(channel, strlen(channel), &mudstate.channel_htab);
01821
01822 for (j = 0; j < ch->num_users; j++)
01823 {
01824 MEMFREE(ch->users[j]);
01825 ch->users[j] = NULL;
01826 }
01827 MEMFREE(ch->users);
01828 ch->users = NULL;
01829 MEMFREE(ch);
01830 ch = NULL;
01831 raw_notify(executor, tprintf("Channel %s destroyed.", channel));
01832 }
01833
01834 #if 0
01835 void do_cleanupchannels(void)
01836 {
01837 struct channel *ch;
01838 for (ch = (struct channel *)hash_firstentry(&mudstate.channel_htab);
01839 ch; ch = (struct channel *)hash_nextentry(&mudstate.channel_htab))
01840 {
01841 struct comuser *user, *prevuser = NULL;
01842 for (user = ch->on_users; user; )
01843 {
01844 if (isPlayer(user->who))
01845 {
01846 if (!test_join_access(user->who, ch))
01847
01848 {
01849
01850
01851 bool bFound = false;
01852 int iPos;
01853 for (iPos = 0; iPos < ch->num_users && !bFound; iPos++)
01854 {
01855 if (ch->users[iPos] == user)
01856 {
01857 bFound = true;
01858 }
01859 }
01860
01861 if (bFound)
01862 {
01863
01864
01865 ch->num_users--;
01866 for (iPos--; iPos < ch->num_users; iPos++)
01867 {
01868 ch->users[iPos] = ch->users[iPos+1];
01869 }
01870
01871
01872
01873 struct comuser *cuVictim = user;
01874
01875
01876
01877 if (prevuser)
01878 {
01879 prevuser->on_next = user->on_next;
01880 }
01881 else
01882 {
01883 ch->on_users = user->on_next;
01884 }
01885 user = user->on_next;
01886
01887
01888
01889 if (!Hidden(cuVictim->who))
01890 {
01891 char *mess = StartBuildChannelMessage(cuVictim->who,
01892 (ch->type & CHANNEL_SPOOF) != 0, ch->header, cuVictim->title,
01893 Moniker(cuVictim->who), ":is booted off the channel by the system.");
01894 do_comsend(ch, mess);
01895 EndBuildChannelMessage(mess);
01896 }
01897 raw_notify(cuVictim->who, tprintf("The system has booted you off channel %s.", ch->name));
01898
01899
01900
01901 if (cuVictim->title)
01902 {
01903 MEMFREE(cuVictim->title);
01904 cuVictim->title = NULL;
01905 }
01906 MEMFREE(cuVictim);
01907 cuVictim = NULL;
01908
01909 continue;
01910 }
01911 }
01912 }
01913
01914 prevuser = user;
01915 user = user->on_next;
01916 }
01917 }
01918 }
01919 #endif
01920
01921 static void do_listchannels(dbref player)
01922 {
01923 struct channel *ch;
01924 char temp[LBUF_SIZE];
01925
01926 bool perm = Comm_All(player);
01927 if (!perm)
01928 {
01929 raw_notify(player, "Warning: Only public channels and your channels will be shown.");
01930 }
01931 raw_notify(player, "*** Channel --Flags-- Obj Own Charge Balance Users Messages");
01932
01933 for (ch = (struct channel *)hash_firstentry(&mudstate.channel_htab);
01934 ch; ch = (struct channel *)hash_nextentry(&mudstate.channel_htab))
01935 {
01936 if ( perm
01937 || (ch->type & CHANNEL_PUBLIC)
01938 || Controls(player, ch->charge_who))
01939 {
01940 sprintf(temp, "%c%c%c %-13.13s %c%c%c/%c%c%c %5d %5d %8d %8d %6d %10d",
01941 (ch->type & CHANNEL_PUBLIC) ? 'P' : '-',
01942 (ch->type & CHANNEL_LOUD) ? 'L' : '-',
01943 (ch->type & CHANNEL_SPOOF) ? 'S' : '-',
01944 ch->name,
01945 (ch->type & CHANNEL_PLAYER_JOIN) ? 'J' : '-',
01946 (ch->type & CHANNEL_PLAYER_TRANSMIT) ? 'X' : '-',
01947 (ch->type & CHANNEL_PLAYER_RECEIVE) ? 'R' : '-',
01948 (ch->type & CHANNEL_OBJECT_JOIN) ? 'j' : '-',
01949 (ch->type & CHANNEL_OBJECT_TRANSMIT) ? 'x' : '-',
01950 (ch->type & CHANNEL_OBJECT_RECEIVE) ? 'r' : '-',
01951 (ch->chan_obj != NOTHING) ? ch->chan_obj : -1,
01952 ch->charge_who, ch->charge, ch->amount_col, ch->num_users, ch->num_messages);
01953 raw_notify(player, temp);
01954 }
01955 }
01956 raw_notify(player, "-- End of list of Channels --");
01957 }
01958
01959 void do_comtitle
01960 (
01961 dbref executor,
01962 dbref caller,
01963 dbref enactor,
01964 int key,
01965 int nargs,
01966 char *arg1,
01967 char *arg2
01968 )
01969 {
01970 UNUSED_PARAMETER(caller);
01971 UNUSED_PARAMETER(enactor);
01972 UNUSED_PARAMETER(nargs);
01973
01974 if (!mudconf.have_comsys)
01975 {
01976 raw_notify(executor, "Comsys disabled.");
01977 return;
01978 }
01979 if (!*arg1)
01980 {
01981 raw_notify(executor, "Need an alias to do comtitle.");
01982 return;
01983 }
01984
01985 char channel[MAX_CHANNEL_LEN+1];
01986 strcpy(channel, get_channel_from_alias(executor, arg1));
01987
01988 if (channel[0] == '\0')
01989 {
01990 raw_notify(executor, "Unknown alias.");
01991 return;
01992 }
01993 struct channel *ch = select_channel(channel);
01994 if (ch)
01995 {
01996 if (select_user(ch, executor))
01997 {
01998 if (key == COMTITLE_OFF)
01999 {
02000 if ((ch->type & CHANNEL_SPOOF) == 0)
02001 {
02002 raw_notify(executor, tprintf("Comtitles are now off for channel %s", channel));
02003 do_setcomtitlestatus(executor, ch, false);
02004 }
02005 else
02006 {
02007 raw_notify(executor, "You can not turn off comtitles on that channel.");
02008 }
02009 }
02010 else if (key == COMTITLE_ON)
02011 {
02012 raw_notify(executor, tprintf("Comtitles are now on for channel %s", channel));
02013 do_setcomtitlestatus(executor, ch, true);
02014 }
02015 else
02016 {
02017 char *pValidatedTitleValue = RestrictTitleValue(arg2);
02018 do_setnewtitle(executor, ch, pValidatedTitleValue);
02019 raw_notify(executor, tprintf("Title set to '%s' on channel %s.",
02020 pValidatedTitleValue, channel));
02021 }
02022 }
02023 }
02024 else
02025 {
02026 raw_notify(executor, "Illegal comsys alias, please delete.");
02027 }
02028 }
02029
02030 void do_comlist
02031 (
02032 dbref executor,
02033 dbref caller,
02034 dbref enactor,
02035 int key,
02036 char* pattern
02037 )
02038 {
02039 UNUSED_PARAMETER(caller);
02040 UNUSED_PARAMETER(enactor);
02041 UNUSED_PARAMETER(key);
02042
02043 if (!mudconf.have_comsys)
02044 {
02045 raw_notify(executor, "Comsys disabled.");
02046 return;
02047 }
02048
02049 bool bWild;
02050 if ( NULL != pattern
02051 && '\0' != *pattern)
02052 {
02053 bWild = true;
02054 }
02055 else
02056 {
02057 bWild = false;
02058 }
02059
02060 raw_notify(executor, "Alias Channel Status Title");
02061
02062 comsys_t *c = get_comsys(executor);
02063 int i;
02064 for (i = 0; i < c->numchannels; i++)
02065 {
02066 struct comuser *user = select_user(select_channel(c->channels[i]), executor);
02067 if (user)
02068 {
02069 if ( !bWild
02070 || quick_wild(pattern,c->channels[i]))
02071 {
02072 char *p =
02073 tprintf("%-9.9s %-18.18s %s %s %s",
02074 c->alias + i * ALIAS_SIZE,
02075 c->channels[i],
02076 (user->bUserIsOn ? "on " : "off"),
02077 (user->ComTitleStatus ? "con " : "coff"),
02078 user->title);
02079 raw_notify(executor, p);
02080 }
02081 }
02082 else
02083 {
02084 raw_notify(executor, tprintf("Bad Comsys Alias: %s for Channel: %s", c->alias + i * ALIAS_SIZE, c->channels[i]));
02085 }
02086 }
02087 raw_notify(executor, "-- End of comlist --");
02088 }
02089
02090 void do_channelnuke(dbref player)
02091 {
02092 struct channel *ch;
02093 int j;
02094
02095 for (ch = (struct channel *)hash_firstentry(&mudstate.channel_htab);
02096 ch; ch = (struct channel *)hash_nextentry(&mudstate.channel_htab))
02097 {
02098 if (player == ch->charge_who)
02099 {
02100 num_channels--;
02101 hashdeleteLEN(ch->name, strlen(ch->name), &mudstate.channel_htab);
02102
02103 for (j = 0; j < ch->num_users; j++)
02104 {
02105 MEMFREE(ch->users[j]);
02106 ch->users[j] = NULL;
02107 }
02108 MEMFREE(ch->users);
02109 ch->users = NULL;
02110 MEMFREE(ch);
02111 ch = NULL;
02112 }
02113 }
02114 }
02115
02116 void do_clearcom(dbref executor, dbref caller, dbref enactor, int unused2)
02117 {
02118 UNUSED_PARAMETER(unused2);
02119
02120 if (!mudconf.have_comsys)
02121 {
02122 raw_notify(executor, "Comsys disabled.");
02123 return;
02124 }
02125 comsys_t *c = get_comsys(executor);
02126
02127 int i;
02128 for (i = (c->numchannels) - 1; i > -1; --i)
02129 {
02130 do_delcom(executor, caller, enactor, 0, c->alias + i * ALIAS_SIZE);
02131 }
02132 }
02133
02134 void do_allcom(dbref executor, dbref caller, dbref enactor, int key, char *arg1)
02135 {
02136 UNUSED_PARAMETER(caller);
02137 UNUSED_PARAMETER(enactor);
02138 UNUSED_PARAMETER(key);
02139
02140 if (!mudconf.have_comsys)
02141 {
02142 raw_notify(executor, "Comsys disabled.");
02143 return;
02144 }
02145 if ( strcmp(arg1, "who") != 0
02146 && strcmp(arg1, "on") != 0
02147 && strcmp(arg1, "off") != 0)
02148 {
02149 raw_notify(executor, "Only options available are: on, off and who.");
02150 return;
02151 }
02152
02153 comsys_t *c = get_comsys(executor);
02154 int i;
02155 for (i = 0; i < c->numchannels; i++)
02156 {
02157 do_processcom(executor, c->channels[i], arg1);
02158 if (strcmp(arg1, "who") == 0)
02159 {
02160 raw_notify(executor, "");
02161 }
02162 }
02163 }
02164
02165 void sort_users(struct channel *ch)
02166 {
02167 int i;
02168 bool done = false;
02169 struct comuser *user;
02170 int nu = ch->num_users;
02171
02172 while (!done)
02173 {
02174 done = true;
02175 for (i = 0; i < (nu - 1); i++)
02176 {
02177 if (ch->users[i]->who > ch->users[i + 1]->who)
02178 {
02179 user = ch->users[i];
02180 ch->users[i] = ch->users[i + 1];
02181 ch->users[i + 1] = user;
02182 done = false;
02183 }
02184 }
02185 }
02186 }
02187
02188 void do_channelwho(dbref executor, dbref caller, dbref enactor, int key, char *arg1)
02189 {
02190 UNUSED_PARAMETER(caller);
02191 UNUSED_PARAMETER(enactor);
02192 UNUSED_PARAMETER(key);
02193
02194 if (!mudconf.have_comsys)
02195 {
02196 raw_notify(executor, "Comsys disabled.");
02197 return;
02198 }
02199
02200 char channel[MAX_CHANNEL_LEN+1];
02201 char *s = arg1;
02202 char *t = channel;
02203 while (*s && *s != '/' && ((t - channel) < MAX_CHANNEL_LEN))
02204 {
02205 *t++ = *s++;
02206 }
02207 *t = 0;
02208
02209 bool flag = false;
02210 if (*s && *(s + 1))
02211 {
02212 flag = (*(s + 1) == 'a');
02213 }
02214
02215 struct channel *ch = select_channel(channel);
02216 if (!ch)
02217 {
02218 raw_notify(executor, tprintf("Unknown channel %s.", channel));
02219 return;
02220 }
02221 if ( !( Comm_All(executor)
02222 || Controls(executor,ch->charge_who)))
02223 {
02224 raw_notify(executor, NOPERM_MESSAGE);
02225 return;
02226 }
02227 raw_notify(executor, tprintf("-- %s --", ch->name));
02228 raw_notify(executor, tprintf("%-29.29s %-6.6s %-6.6s", "Name", "Status", "Player"));
02229 struct comuser *user;
02230 char *buff;
02231 char temp[LBUF_SIZE];
02232 int i;
02233 for (i = 0; i < ch->num_users; i++)
02234 {
02235 user = ch->users[i];
02236 if ( ( flag
02237 || UNDEAD(user->who))
02238 && ( !Hidden(user->who)
02239 || Wizard_Who(executor)
02240 || See_Hidden(executor)))
02241 {
02242 buff = unparse_object(executor, user->who, false);
02243 sprintf(temp, "%-29.29s %-6.6s %-6.6s", strip_ansi(buff),
02244 user->bUserIsOn ? "on " : "off",
02245 isPlayer(user->who) ? "yes" : "no ");
02246 raw_notify(executor, temp);
02247 free_lbuf(buff);
02248 }
02249 }
02250 raw_notify(executor, tprintf("-- %s --", ch->name));
02251 }
02252
02253 static void do_comdisconnectraw_notify(dbref player, char *chan)
02254 {
02255 struct channel *ch = select_channel(chan);
02256 if (!ch) return;
02257
02258 struct comuser *cu = select_user(ch, player);
02259 if (!cu) return;
02260
02261 if ( (ch->type & CHANNEL_LOUD)
02262 && cu->bUserIsOn
02263 && !Hidden(player))
02264 {
02265 char *messNormal, *messNoComtitle;
02266 BuildChannelMessage((ch->type & CHANNEL_SPOOF) != 0, ch->header, cu,
02267 ":has disconnected.", &messNormal, &messNoComtitle);
02268 SendChannelMessage(player, ch, messNormal, messNoComtitle);
02269 }
02270 }
02271
02272 static void do_comconnectraw_notify(dbref player, char *chan)
02273 {
02274 struct channel *ch = select_channel(chan);
02275 if (!ch) return;
02276 struct comuser *cu = select_user(ch, player);
02277 if (!cu) return;
02278
02279 if ( (ch->type & CHANNEL_LOUD)
02280 && cu->bUserIsOn
02281 && !Hidden(player))
02282 {
02283 char *messNormal, *messNoComtitle;
02284 BuildChannelMessage((ch->type & CHANNEL_SPOOF) != 0, ch->header, cu,
02285 ":has connected.", &messNormal, &messNoComtitle);
02286 SendChannelMessage(player, ch, messNormal, messNoComtitle);
02287 }
02288 }
02289
02290 static void do_comconnectchannel(dbref player, char *channel, char *alias, int i)
02291 {
02292 struct comuser *user;
02293
02294 struct channel *ch = select_channel(channel);
02295 if (ch)
02296 {
02297 for (user = ch->on_users;
02298 user && user->who != player;
02299 user = user->on_next) ;
02300
02301 if (!user)
02302 {
02303 user = select_user(ch, player);
02304 if (user)
02305 {
02306 user->on_next = ch->on_users;
02307 ch->on_users = user;
02308 }
02309 else
02310 {
02311 raw_notify(player, tprintf("Bad Comsys Alias: %s for Channel: %s", alias + i * ALIAS_SIZE, channel));
02312 }
02313 }
02314 }
02315 else
02316 {
02317 raw_notify(player, tprintf("Bad Comsys Alias: %s for Channel: %s", alias + i * ALIAS_SIZE, channel));
02318 }
02319 }
02320
02321 void do_comdisconnect(dbref player)
02322 {
02323 comsys_t *c = get_comsys(player);
02324 int i;
02325
02326 for (i = 0; i < c->numchannels; i++)
02327 {
02328 char *CurrentChannel = c->channels[i];
02329 bool bFound = false;
02330 int j;
02331
02332 for (j = 0; j < i; j++)
02333 {
02334 if (strcmp(c->channels[j], CurrentChannel) == 0)
02335 {
02336 bFound = true;
02337 break;
02338 }
02339 }
02340
02341 if (!bFound)
02342 {
02343 do_comdisconnectchannel(player, CurrentChannel);
02344 do_comdisconnectraw_notify(player, CurrentChannel);
02345 }
02346 }
02347 }
02348
02349 void do_comconnect(dbref player)
02350 {
02351 comsys_t *c = get_comsys(player);
02352 int i;
02353
02354 for (i = 0; i < c->numchannels; i++)
02355 {
02356 char *CurrentChannel = c->channels[i];
02357 bool bFound = false;
02358 int j;
02359
02360 for (j = 0; j < i; j++)
02361 {
02362 if (strcmp(c->channels[j], CurrentChannel) == 0)
02363 {
02364 bFound = true;
02365 break;
02366 }
02367 }
02368
02369 if (!bFound)
02370 {
02371 do_comconnectchannel(player, CurrentChannel, c->alias, i);
02372 do_comconnectraw_notify(player, CurrentChannel);
02373 }
02374 }
02375 }
02376
02377
02378 void do_comdisconnectchannel(dbref player, char *channel)
02379 {
02380 struct channel *ch = select_channel(channel);
02381 if (!ch)
02382 {
02383 return;
02384 }
02385
02386 struct comuser *prevuser = NULL;
02387 struct comuser *user;
02388 for (user = ch->on_users; user;)
02389 {
02390 if (user->who == player)
02391 {
02392 if (prevuser)
02393 {
02394 prevuser->on_next = user->on_next;
02395 }
02396 else
02397 {
02398 ch->on_users = user->on_next;
02399 }
02400 return;
02401 }
02402 else
02403 {
02404 prevuser = user;
02405 user = user->on_next;
02406 }
02407 }
02408 }
02409
02410 void do_editchannel
02411 (
02412 dbref executor,
02413 dbref caller,
02414 dbref enactor,
02415 int flag,
02416 int nargs,
02417 char *arg1,
02418 char *arg2
02419 )
02420 {
02421 UNUSED_PARAMETER(caller);
02422 UNUSED_PARAMETER(enactor);
02423 UNUSED_PARAMETER(nargs);
02424
02425 if (!mudconf.have_comsys)
02426 {
02427 raw_notify(executor, "Comsys disabled.");
02428 return;
02429 }
02430 struct channel *ch = select_channel(arg1);
02431 if (!ch)
02432 {
02433 raw_notify(executor, tprintf("Unknown channel %s.", arg1));
02434 return;
02435 }
02436 if ( !( Comm_All(executor)
02437 || Controls(executor, ch->charge_who)))
02438 {
02439 raw_notify(executor, NOPERM_MESSAGE);
02440 return;
02441 }
02442
02443 bool add_remove = true;
02444 char *s = arg2;
02445 if (*s == '!')
02446 {
02447 add_remove = false;
02448 s++;
02449 }
02450 switch (flag)
02451 {
02452 case 0:
02453 {
02454 dbref who = lookup_player(executor, arg2, true);
02455 if (NOTHING == who)
02456 {
02457 raw_notify(executor, "Invalid player.");
02458 }
02459 else
02460 {
02461 ch->charge_who = who;
02462 raw_notify(executor, "Set.");
02463 }
02464 }
02465 break;
02466
02467 case 1:
02468 ch->charge = mux_atol(arg2);
02469 raw_notify(executor, "Set.");
02470 break;
02471
02472 case 3:
02473 {
02474 int access = 0;
02475 if (strcmp(s, "join") == 0)
02476 {
02477 access = CHANNEL_PLAYER_JOIN;
02478 }
02479 else if (strcmp(s, "receive") == 0)
02480 {
02481 access = CHANNEL_PLAYER_RECEIVE;
02482 }
02483 else if (strcmp(s, "transmit") == 0)
02484 {
02485 access = CHANNEL_PLAYER_TRANSMIT;
02486 }
02487 else
02488 {
02489 raw_notify(executor, "@cpflags: Unknown Flag.");
02490 }
02491
02492 if (access)
02493 {
02494 if (add_remove)
02495 {
02496 ch->type |= access;
02497 raw_notify(executor, "@cpflags: Set.");
02498 }
02499 else
02500 {
02501 ch->type &= ~access;
02502 raw_notify(executor, "@cpflags: Cleared.");
02503 }
02504 }
02505 }
02506 break;
02507
02508 case 4:
02509 {
02510 int access = 0;
02511 if (strcmp(s, "join") == 0)
02512 {
02513 access = CHANNEL_OBJECT_JOIN;
02514 }
02515 else if (strcmp(s, "receive") == 0)
02516 {
02517 access = CHANNEL_OBJECT_RECEIVE;
02518 }
02519 else if (strcmp(s, "transmit") == 0)
02520 {
02521 access = CHANNEL_OBJECT_TRANSMIT;
02522 }
02523 else
02524 {
02525 raw_notify(executor, "@coflags: Unknown Flag.");
02526 }
02527
02528 if (access)
02529 {
02530 if (add_remove)
02531 {
02532 ch->type |= access;
02533 raw_notify(executor, "@coflags: Set.");
02534 }
02535 else
02536 {
02537 ch->type &= ~access;
02538 raw_notify(executor, "@coflags: Cleared.");
02539 }
02540 }
02541 }
02542 break;
02543 }
02544 }
02545
02546 bool test_join_access(dbref player, struct channel *chan)
02547 {
02548 if (Comm_All(player))
02549 {
02550 return true;
02551 }
02552
02553 int access;
02554 if (isPlayer(player))
02555 {
02556 access = CHANNEL_PLAYER_JOIN;
02557 }
02558 else
02559 {
02560 access = CHANNEL_OBJECT_JOIN;
02561 }
02562 return ( (chan->type & access) != 0
02563 || could_doit(player, chan->chan_obj, A_LOCK));
02564 }
02565
02566 bool test_transmit_access(dbref player, struct channel *chan)
02567 {
02568 if (Comm_All(player))
02569 {
02570 return true;
02571 }
02572
02573 int access;
02574 if (isPlayer(player))
02575 {
02576 access = CHANNEL_PLAYER_TRANSMIT;
02577 }
02578 else
02579 {
02580 access = CHANNEL_OBJECT_TRANSMIT;
02581 }
02582 return ( (chan->type & access) != 0
02583 || could_doit(player, chan->chan_obj, A_LUSE));
02584
02585 }
02586
02587 bool test_receive_access(dbref player, struct channel *chan)
02588 {
02589 if (Comm_All(player))
02590 {
02591 return true;
02592 }
02593
02594 int access;
02595 if (isPlayer(player))
02596 {
02597 access = CHANNEL_PLAYER_RECEIVE;
02598 }
02599 else
02600 {
02601 access = CHANNEL_OBJECT_RECEIVE;
02602 }
02603 return ( (chan->type & access) != 0
02604 || could_doit(player, chan->chan_obj, A_LENTER));
02605
02606 }
02607
02608
02609
02610 bool do_comsystem(dbref who, char *cmd)
02611 {
02612 char *t;
02613 char *alias = alloc_lbuf("do_comsystem");
02614 char *s = alias;
02615 for (t = cmd; *t && *t != ' ' && s < alias + LBUF_SIZE; *s++ = *t++)
02616 {
02617 ;
02618 }
02619
02620 *s = '\0';
02621
02622 if (*t)
02623 {
02624 t++;
02625 }
02626
02627 char *ch = get_channel_from_alias(who, alias);
02628 if ( ch[0] != '\0'
02629 && t[0] != '\0')
02630 {
02631 do_processcom(who, ch, t);
02632 free_lbuf(alias);
02633 return false;
02634 }
02635 else
02636 {
02637 free_lbuf(alias);
02638 }
02639 return true;
02640 }
02641
02642 void do_cemit
02643 (
02644 dbref executor,
02645 dbref caller,
02646 dbref enactor,
02647 int key,
02648 int nargs,
02649 char *chan,
02650 char *text
02651 )
02652 {
02653 UNUSED_PARAMETER(caller);
02654 UNUSED_PARAMETER(enactor);
02655 UNUSED_PARAMETER(nargs);
02656
02657 if (!mudconf.have_comsys)
02658 {
02659 raw_notify(executor, "Comsys disabled.");
02660 return;
02661 }
02662 struct channel *ch = select_channel(chan);
02663 if (!ch)
02664 {
02665 raw_notify(executor, tprintf("Channel %s does not exist.", chan));
02666 return;
02667 }
02668 if ( !Controls(executor, ch->charge_who)
02669 && !Comm_All(executor))
02670 {
02671 raw_notify(executor, NOPERM_MESSAGE);
02672 return;
02673 }
02674 char *text2 = alloc_lbuf("do_cemit");
02675 if (key == CEMIT_NOHEADER)
02676 {
02677 strcpy(text2, text);
02678 }
02679 else
02680 {
02681 strcpy(text2, tprintf("%s %s", ch->header, text));
02682 }
02683 SendChannelMessage(executor, ch, text2, text2);
02684 }
02685
02686 void do_chopen
02687 (
02688 dbref executor,
02689 dbref caller,
02690 dbref enactor,
02691 int key,
02692 int nargs,
02693 char *chan,
02694 char *value
02695 )
02696 {
02697 UNUSED_PARAMETER(nargs);
02698
02699 if (!mudconf.have_comsys)
02700 {
02701 raw_notify(executor, "Comsys disabled.");
02702 return;
02703 }
02704 if (key == CSET_LIST)
02705 {
02706 do_chanlist(executor, caller, enactor, 1, NULL);
02707 return;
02708 }
02709
02710 char *msg = NULL;
02711 struct channel *ch = select_channel(chan);
02712 if (!ch)
02713 {
02714 msg = tprintf("@cset: Channel %s does not exist.", chan);
02715 raw_notify(executor, msg);
02716 return;
02717 }
02718 if ( !Controls(executor, ch->charge_who)
02719 && !Comm_All(executor))
02720 {
02721 raw_notify(executor, NOPERM_MESSAGE);
02722 return;
02723 }
02724 char *buff;
02725 dbref thing;
02726
02727 switch (key)
02728 {
02729 case CSET_PUBLIC:
02730 ch->type |= CHANNEL_PUBLIC;
02731 msg = tprintf("@cset: Channel %s placed on the public listings.", chan);
02732 break;
02733
02734 case CSET_PRIVATE:
02735 ch->type &= ~CHANNEL_PUBLIC;
02736 msg = tprintf("@cset: Channel %s taken off the public listings." ,chan);
02737 break;
02738
02739 case CSET_LOUD:
02740 ch->type |= CHANNEL_LOUD;
02741 msg = tprintf("@cset: Channel %s now sends connect/disconnect msgs.", chan);
02742 break;
02743
02744 case CSET_QUIET:
02745 ch->type &= ~CHANNEL_LOUD;
02746 msg = tprintf("@cset: Channel %s connect/disconnect msgs muted.", chan);
02747 break;
02748
02749 case CSET_SPOOF:
02750 ch->type |= CHANNEL_SPOOF;
02751 msg = tprintf("@cset: Channel %s set spoofable.", chan);
02752 break;
02753
02754 case CSET_NOSPOOF:
02755 ch->type &= ~CHANNEL_SPOOF;
02756 msg = tprintf("@cset: Channel %s set unspoofable.", chan);
02757 break;
02758
02759 case CSET_OBJECT:
02760 init_match(executor, value, NOTYPE);
02761 match_everything(0);
02762 thing = match_result();
02763
02764 if (thing == NOTHING)
02765 {
02766 ch->chan_obj = thing;
02767 msg = tprintf("Channel %s is now disassociated from any channel object.", ch->name);
02768 }
02769 else if (Good_obj(thing))
02770 {
02771 ch->chan_obj = thing;
02772 buff = unparse_object(executor, thing, false);
02773 msg = tprintf("Channel %s is now using %s as channel object.", ch->name, buff);
02774 free_lbuf(buff);
02775 }
02776 else
02777 {
02778 msg = tprintf("%d is not a valid channel object.", thing);
02779 }
02780 break;
02781
02782 case CSET_HEADER:
02783 do_cheader(executor, chan, value);
02784 msg = "Set.";
02785 break;
02786
02787 case CSET_LOG:
02788 if (do_chanlog(executor, chan, value))
02789 {
02790 msg = tprintf("@cset: Channel %s maximum history set.", chan);
02791 }
02792 else
02793 {
02794 msg = tprintf("@cset: Maximum history must be a number less than or equal to %d.", MAX_RECALL_REQUEST);
02795 }
02796 break;
02797 }
02798 raw_notify(executor, msg);
02799 }
02800
02801 void do_chboot
02802 (
02803 dbref executor,
02804 dbref caller,
02805 dbref enactor,
02806 int key,
02807 int nargs,
02808 char *channel,
02809 char *victim
02810 )
02811 {
02812 UNUSED_PARAMETER(caller);
02813 UNUSED_PARAMETER(enactor);
02814 UNUSED_PARAMETER(nargs);
02815
02816
02817
02818 if (!mudconf.have_comsys)
02819 {
02820 raw_notify(executor, "Comsys disabled.");
02821 return;
02822 }
02823 struct channel *ch = select_channel(channel);
02824 if (!ch)
02825 {
02826 raw_notify(executor, "@cboot: Unknown channel.");
02827 return;
02828 }
02829 struct comuser *user = select_user(ch, executor);
02830 if (!user)
02831 {
02832 raw_notify(executor, "@cboot: You are not on that channel.");
02833 return;
02834 }
02835 if ( !Controls(executor, ch->charge_who)
02836 && !Comm_All(executor))
02837 {
02838 raw_notify(executor, "@cboot: You can't do that!");
02839 return;
02840 }
02841 dbref thing = match_thing(executor, victim);
02842
02843 if (!Good_obj(thing))
02844 {
02845 return;
02846 }
02847 struct comuser *vu = select_user(ch, thing);
02848 if (!vu)
02849 {
02850 raw_notify(executor, tprintf("@cboot: %s is not on the channel.",
02851 Moniker(thing)));
02852 return;
02853 }
02854
02855 raw_notify(executor, tprintf("You boot %s off channel %s.",
02856 Moniker(thing), ch->name));
02857 raw_notify(thing, tprintf("%s boots you off channel %s.",
02858 Moniker(thing), ch->name));
02859
02860 if (!(key & CBOOT_QUIET))
02861 {
02862 char *mess1, *mess1nct;
02863 char *mess2, *mess2nct;
02864 BuildChannelMessage((ch->type & CHANNEL_SPOOF) != 0, ch->header, user,
02865 ":boots", &mess1, &mess1nct);
02866 BuildChannelMessage((ch->type & CHANNEL_SPOOF) != 0, 0, vu,
02867 ":off the channel.", &mess2, &mess2nct);
02868 char *messNormal = alloc_lbuf("do_chboot.messnormal");
02869 char *messNoComtitle = alloc_lbuf("do_chboot.messnocomtitle");
02870 char *mnp = messNormal;
02871 char *mnctp = messNoComtitle;
02872 if (mess1)
02873 {
02874 safe_str(mess1, messNormal, &mnp);
02875 free_lbuf(mess1);
02876 }
02877 if (mess2)
02878 {
02879 safe_str(mess2, messNormal, &mnp);
02880 free_lbuf(mess2);
02881 }
02882 *mnp = '\0';
02883 if (mess1nct)
02884 {
02885 safe_str(mess1nct, messNoComtitle, &mnctp);
02886 free_lbuf(mess1nct);
02887 }
02888 if (mess2nct)
02889 {
02890 safe_str(mess2nct, messNoComtitle, &mnctp);
02891 free_lbuf(mess2nct);
02892 }
02893 *mnctp = '\0';
02894 SendChannelMessage(executor, ch, messNormal, messNoComtitle);
02895 do_delcomchannel(thing, channel, false);
02896 }
02897 else
02898 {
02899 do_delcomchannel(thing, channel, true);
02900 }
02901 }
02902
02903 void do_cheader(dbref player, char *channel, char *header)
02904 {
02905 struct channel *ch = select_channel(channel);
02906 if (!ch)
02907 {
02908 raw_notify(player, "That channel does not exist.");
02909 return;
02910 }
02911 if ( !Controls(player, ch->charge_who)
02912 && !Comm_All(player))
02913 {
02914 raw_notify(player, NOPERM_MESSAGE);
02915 return;
02916 }
02917 char *p = RemoveSetOfCharacters(header, "\r\n\t");
02918
02919
02920
02921 char NewHeader_ANSI[MAX_HEADER_LEN+1];
02922 int nVisualWidth;
02923 int nLen = ANSI_TruncateToField(p, sizeof(NewHeader_ANSI),
02924 NewHeader_ANSI, sizeof(NewHeader_ANSI), &nVisualWidth,
02925 ANSI_ENDGOAL_NORMAL);
02926 memcpy(ch->header, NewHeader_ANSI, nLen+1);
02927 }
02928
02929 struct chanlist_node
02930 {
02931 char * name;
02932 struct channel * ptr;
02933 };
02934
02935 static int DCL_CDECL chanlist_comp(const void* a, const void* b)
02936 {
02937 chanlist_node* ca = (chanlist_node*)a;
02938 chanlist_node* cb = (chanlist_node*)b;
02939 return mux_stricmp(ca->name, cb->name);
02940 }
02941
02942 void do_chanlist
02943 (
02944 dbref executor,
02945 dbref caller,
02946 dbref enactor,
02947 int key,
02948 char *pattern
02949 )
02950 {
02951 UNUSED_PARAMETER(caller);
02952 UNUSED_PARAMETER(enactor);
02953
02954 if (!mudconf.have_comsys)
02955 {
02956 raw_notify(executor, "Comsys disabled.");
02957 return;
02958 }
02959 if (key & CLIST_FULL)
02960 {
02961 do_listchannels(executor);
02962 return;
02963 }
02964
02965 dbref owner;
02966 struct channel *ch;
02967 int flags = 0;
02968 char *atrstr;
02969 char *temp = alloc_mbuf("do_chanlist_temp");
02970 char *buf = alloc_mbuf("do_chanlist_buf");
02971
02972 if (key & CLIST_HEADERS)
02973 {
02974 raw_notify(executor, "*** Channel Owner Header");
02975 }
02976 else
02977 {
02978 raw_notify(executor, "*** Channel Owner Description");
02979 }
02980
02981 bool bWild;
02982 if ( NULL != pattern
02983 && '\0' != *pattern)
02984 {
02985 bWild = true;
02986 }
02987 else
02988 {
02989 bWild = false;
02990 }
02991
02992 #define MAX_SUPPORTED_NUM_ENTRIES 10000
02993
02994 INT64 iEntryCount64 = mudstate.channel_htab.GetEntryCount();
02995 if (MAX_SUPPORTED_NUM_ENTRIES < iEntryCount64)
02996 {
02997
02998
02999 iEntryCount64 = MAX_SUPPORTED_NUM_ENTRIES;
03000 }
03001 size_t entries = (size_t)iEntryCount64;
03002
03003 struct chanlist_node* charray = (chanlist_node*)MEMALLOC(sizeof(chanlist_node)*entries);
03004 ISOUTOFMEMORY(charray);
03005
03006
03007
03008 size_t actualEntries;
03009 for ( actualEntries = 0, ch = (struct channel *)hash_firstentry(&mudstate.channel_htab);
03010 ch
03011 && actualEntries < entries;
03012 ch = (struct channel *)hash_nextentry(&mudstate.channel_htab))
03013 {
03014 if ( !bWild
03015 || quick_wild(pattern, ch->name))
03016 {
03017 charray[actualEntries].name = ch->name;
03018 charray[actualEntries].ptr = ch;
03019 actualEntries++;
03020 }
03021 }
03022
03023 qsort(charray, actualEntries, sizeof(struct chanlist_node), chanlist_comp);
03024
03025 for (size_t i = 0; i < actualEntries; i++)
03026 {
03027 ch = charray[i].ptr;
03028 if ( Comm_All(executor)
03029 || (ch->type & CHANNEL_PUBLIC)
03030 || Controls(executor, ch->charge_who))
03031 {
03032 char *pBuffer;
03033 if (key & CLIST_HEADERS)
03034 {
03035 pBuffer = ch->header;
03036 }
03037 else
03038 {
03039 atrstr = atr_pget(ch->chan_obj, A_DESC, &owner, &flags);
03040 if ( NOTHING == ch->chan_obj
03041 || !*atrstr)
03042 {
03043 strcpy(buf, "No description.");
03044 }
03045 else
03046 {
03047 sprintf(buf, "%-54.54s", atrstr);
03048 }
03049 free_lbuf(atrstr);
03050
03051 pBuffer = buf;
03052 }
03053
03054 char *ownername_ansi = ANSI_TruncateAndPad_sbuf(Moniker(ch->charge_who), 15);
03055 sprintf(temp, "%c%c%c %-13.13s %s %-45.45s",
03056 (ch->type & (CHANNEL_PUBLIC)) ? 'P' : '-',
03057 (ch->type & (CHANNEL_LOUD)) ? 'L' : '-',
03058 (ch->type & (CHANNEL_SPOOF)) ? 'S' : '-',
03059 ch->name, ownername_ansi, pBuffer);
03060 free_sbuf(ownername_ansi);
03061
03062 raw_notify(executor, temp);
03063 }
03064 }
03065 MEMFREE(charray);
03066 free_mbuf(temp);
03067 free_mbuf(buf);
03068 raw_notify(executor, "-- End of list of Channels --");
03069 }
03070
03071
03072
03073 FUNCTION(fun_comtitle)
03074 {
03075 UNUSED_PARAMETER(caller);
03076 UNUSED_PARAMETER(enactor);
03077 UNUSED_PARAMETER(nfargs);
03078 UNUSED_PARAMETER(cargs);
03079 UNUSED_PARAMETER(ncargs);
03080
03081 if (!mudconf.have_comsys)
03082 {
03083 safe_str("#-1 COMSYS DISABLED", buff, bufc);
03084 return;
03085 }
03086
03087 dbref victim = lookup_player(executor, fargs[0], true);
03088 if (!Good_obj(victim))
03089 {
03090 init_match(executor, fargs[0], TYPE_THING);
03091 match_everything(0);
03092 victim = match_result();
03093 if (!Good_obj(victim))
03094 {
03095 safe_str("#-1 OBJECT DOES NOT EXIST", buff, bufc);
03096 return;
03097 }
03098 }
03099
03100 struct channel *chn = select_channel(fargs[1]);
03101 if (!chn)
03102 {
03103 safe_str("#-1 CHANNEL DOES NOT EXIST", buff, bufc);
03104 return;
03105 }
03106
03107 comsys_t *c = get_comsys(executor);
03108 struct comuser *user;
03109
03110 int i;
03111 bool onchannel = false;
03112 if (Wizard(executor))
03113 {
03114 onchannel = true;
03115 }
03116 else
03117 {
03118 for (i = 0; i < c->numchannels; i++)
03119 {
03120 user = select_user(chn, executor);
03121 if (user)
03122 {
03123 onchannel = true;
03124 break;
03125 }
03126 }
03127 }
03128
03129 if (!onchannel)
03130 {
03131 safe_noperm(buff, bufc);
03132 return;
03133 }
03134
03135 for (i = 0; i < c->numchannels; i++)
03136 {
03137 user = select_user(chn, victim);
03138 if (user)
03139 {
03140
03141 #if 0
03142 char *nComTitle = GetComtitle(user);
03143 safe_str(nComTitle, buff, bufc);
03144 FreeComtitle(nComTitle);
03145 return;
03146 #else
03147 safe_str(user->title, buff, bufc);
03148 return;
03149 #endif
03150 }
03151 }
03152 safe_str("#-1 OBJECT NOT ON THAT CHANNEL", buff, bufc);
03153 }
03154
03155
03156
03157 FUNCTION(fun_comalias)
03158 {
03159 UNUSED_PARAMETER(caller);
03160 UNUSED_PARAMETER(enactor);
03161 UNUSED_PARAMETER(nfargs);
03162 UNUSED_PARAMETER(cargs);
03163 UNUSED_PARAMETER(ncargs);
03164
03165 if (!mudconf.have_comsys)
03166 {
03167 safe_str("#-1 COMSYS DISABLED", buff, bufc);
03168 return;
03169 }
03170
03171 dbref victim = lookup_player(executor, fargs[0], true);
03172 if (!Good_obj(victim))
03173 {
03174 init_match(executor, fargs[0], TYPE_THING);
03175 match_everything(0);
03176 victim = match_result();
03177 if (!Good_obj(victim))
03178 {
03179 safe_str("#-1 OBJECT DOES NOT EXIST", buff, bufc);
03180 return;
03181 }
03182 }
03183
03184 struct channel *chn = select_channel(fargs[1]);
03185 if (!chn)
03186 {
03187 safe_str("#-1 CHANNEL DOES NOT EXIST", buff, bufc);
03188 return;
03189 }
03190
03191
03192
03193
03194 if ( !Wizard(executor)
03195 && executor != victim
03196 && ( Owner(executor) != victim
03197 || !Inherits(executor)))
03198 {
03199 safe_noperm(buff, bufc);
03200 return;
03201 }
03202
03203 comsys_t *cc = get_comsys(victim);
03204 for (int i = 0; i < cc->numchannels; i++)
03205 {
03206 if (!strcmp(fargs[1], cc->channels[i]))
03207 {
03208 safe_str(cc->alias + i * ALIAS_SIZE, buff, bufc);
03209 return;
03210 }
03211 }
03212 safe_str("#-1 OBJECT NOT ON THAT CHANNEL", buff, bufc);
03213 }
03214
03215
03216
03217 FUNCTION(fun_channels)
03218 {
03219 UNUSED_PARAMETER(caller);
03220 UNUSED_PARAMETER(enactor);
03221 UNUSED_PARAMETER(cargs);
03222 UNUSED_PARAMETER(ncargs);
03223
03224 if (!mudconf.have_comsys)
03225 {
03226 safe_str("#-1 COMSYS DISABLED", buff, bufc);
03227 return;
03228 }
03229
03230 dbref who = NOTHING;
03231 if (nfargs >= 1)
03232 {
03233 who = lookup_player(executor, fargs[0], true);
03234 if ( who == NOTHING
03235 && mux_stricmp(fargs[0], "all") != 0)
03236 {
03237 safe_str("#-1 PLAYER NOT FOUND", buff, bufc);
03238 return;
03239 }
03240 }
03241
03242 ITL itl;
03243 ItemToList_Init(&itl, buff, bufc);
03244 struct channel *chn;
03245 for (chn = (struct channel *)hash_firstentry(&mudstate.channel_htab);
03246 chn;
03247 chn = (struct channel *)hash_nextentry(&mudstate.channel_htab))
03248 {
03249 if ( ( Comm_All(executor)
03250 || (chn->type & CHANNEL_PUBLIC)
03251 || Controls(executor, chn->charge_who))
03252 && ( who == NOTHING
03253 || Controls(who, chn->charge_who))
03254 && !ItemToList_AddString(&itl, chn->name))
03255 {
03256 break;
03257 }
03258 }
03259 }