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) !=