📄 zephyr.c
字号:
continue; if (b->account->gc == gc) { const char *chk; chk = local_zephyr_normalize(zephyr,b->name); purple_debug_info("zephyr","chk: %s b->name %s\n",chk,b->name); /* XXX add real error reporting */ /* doesn't matter if this fails or not; we'll just move on to the next one */ if (use_zeph02(zephyr)) {#ifdef WIN32 int numlocs; int one=1; ZLocateUser(chk,&numlocs,ZAUTH); if (numlocs) { int i; for(i=0;i<numlocs;i++) { ZGetLocations(&locations,&one); if (nlocs>0) purple_prpl_got_user_status(gc->account,b->name,"available",NULL); else purple_prpl_got_user_status(gc->account,b->name,"offline",NULL); } }#else ZRequestLocations(chk, &ald, UNACKED, ZAUTH); g_free(ald.user); g_free(ald.version);#endif /* WIN32 */ } else if (use_tzc(zephyr)) { gchar *zlocstr = g_strdup_printf("((tzcfodder . zlocate) \"%s\")\n",chk); write(zephyr->totzc[ZEPHYR_FD_WRITE],zlocstr,strlen(zlocstr)); g_free(zlocstr); } } } } } return TRUE;}#endif /* WIN32 */static char *get_exposure_level(){ /* XXX add real error reporting */ char *exposure = ZGetVariable("exposure"); if (!exposure) return EXPOSE_REALMVIS; if (!g_ascii_strcasecmp(exposure, EXPOSE_NONE)) return EXPOSE_NONE; if (!g_ascii_strcasecmp(exposure, EXPOSE_OPSTAFF)) return EXPOSE_OPSTAFF; if (!g_ascii_strcasecmp(exposure, EXPOSE_REALMANN)) return EXPOSE_REALMANN; if (!g_ascii_strcasecmp(exposure, EXPOSE_NETVIS)) return EXPOSE_NETVIS; if (!g_ascii_strcasecmp(exposure, EXPOSE_NETANN)) return EXPOSE_NETANN; return EXPOSE_REALMVIS;}static void strip_comments(char *str){ char *tmp = strchr(str, '#'); if (tmp) *tmp = '\0'; g_strchug(str); g_strchomp(str);}static void zephyr_inithosts(zephyr_account *zephyr){ /* XXX This code may not be Win32 clean */ struct hostent *hent; if (gethostname(zephyr->ourhost, sizeof(zephyr->ourhost)) == -1) { purple_debug_error("zephyr", "unable to retrieve hostname, %%host%% and %%canon%% will be wrong in subscriptions and have been set to unknown\n"); g_strlcpy(zephyr->ourhost, "unknown", sizeof(zephyr->ourhost)); g_strlcpy(zephyr->ourhostcanon, "unknown", sizeof(zephyr->ourhostcanon)); return; } if (!(hent = gethostbyname(zephyr->ourhost))) { purple_debug_error("zephyr", "unable to resolve hostname, %%canon%% will be wrong in subscriptions.and has been set to the value of %%host%%, %s\n",zephyr->ourhost); g_strlcpy(zephyr->ourhostcanon, zephyr->ourhost, sizeof(zephyr->ourhostcanon)); return; } g_strlcpy(zephyr->ourhostcanon, hent->h_name, sizeof(zephyr->ourhostcanon)); return;}static void process_zsubs(zephyr_account *zephyr){ /* Loads zephyr chats "(subscriptions) from ~/.zephyr.subs, and registers (subscribes to) them on the server */ /* XXX deal with unsubscriptions */ /* XXX deal with punts */ FILE *f; gchar *fname; gchar buff[BUFSIZ]; fname = g_strdup_printf("%s/.zephyr.subs", purple_home_dir()); f = g_fopen(fname, "r"); if (f) { char **triple; char *recip; char *z_class; char *z_instance; char *z_galaxy = NULL; while (fgets(buff, BUFSIZ, f)) { strip_comments(buff); if (buff[0]) { triple = g_strsplit(buff, ",", 3); if (triple[0] && triple[1]) { char *tmp = g_strdup_printf("%s", zephyr->username); char *atptr; z_class = triple[0]; z_instance = triple[1]; if (triple[2] == NULL) { recip = g_malloc0(1); } else if (!g_ascii_strcasecmp(triple[2], "%me%")) { recip = g_strdup_printf("%s", zephyr->username); } else if (!g_ascii_strcasecmp(triple[2], "*")) { /* wildcard * form of class,instance,* */ recip = g_malloc0(1); } else if (!g_ascii_strcasecmp(triple[2], tmp)) { /* form of class,instance,aatharuv@ATHENA.MIT.EDU */ recip = g_strdup(triple[2]); } else if ((atptr = strchr(triple[2], '@')) != NULL) { /* form of class,instance,*@ANDREW.CMU.EDU * class,instance,@ANDREW.CMU.EDU * If realm is local realm, blank recipient, else * @REALM-NAME */ char *realmat = g_strdup_printf("@%s",zephyr->realm); if (!g_ascii_strcasecmp(atptr, realmat)) recip = g_malloc0(1); else recip = g_strdup(atptr); g_free(realmat); } else { recip = g_strdup(triple[2]); } g_free(tmp); if (!g_ascii_strcasecmp(triple[0],"%host%")) { z_class = g_strdup(zephyr->ourhost); } else if (!g_ascii_strcasecmp(triple[0],"%canon%")) { z_class = g_strdup(zephyr->ourhostcanon); } else { z_class = g_strdup(triple[0]); } if (!g_ascii_strcasecmp(triple[1],"%host%")) { z_instance = g_strdup(zephyr->ourhost); } else if (!g_ascii_strcasecmp(triple[1],"%canon%")) { z_instance = g_strdup(zephyr->ourhostcanon); } else { z_instance = g_strdup(triple[1]); } /* There should be some sort of error report listing classes that couldn't be subbed to. Not important right now though */ if (zephyr_subscribe_to(zephyr,z_class, z_instance, recip,z_galaxy) != ZERR_NONE) { purple_debug_error("zephyr", "Couldn't subscribe to %s, %s, %s\n", z_class,z_instance,recip); } zephyr->subscrips = g_slist_append(zephyr->subscrips, new_triple(zephyr,z_class,z_instance,recip)); /* g_hash_table_destroy(sub_hash_table); */ g_free(z_instance); g_free(z_class); g_free(recip); } g_strfreev(triple); } } fclose(f); }}static void process_anyone(PurpleConnection *gc){ FILE *fd; gchar buff[BUFSIZ], *filename; PurpleGroup *g; PurpleBuddy *b; if (!(g = purple_find_group(_("Anyone")))) { g = purple_group_new(_("Anyone")); purple_blist_add_group(g, NULL); } filename = g_strconcat(purple_home_dir(), "/.anyone", NULL); if ((fd = g_fopen(filename, "r")) != NULL) { while (fgets(buff, BUFSIZ, fd)) { strip_comments(buff); if (buff[0]) { if (!(b = purple_find_buddy(gc->account, buff))) { char *stripped_user = zephyr_strip_local_realm(gc->proto_data,buff); purple_debug_info("zephyr","stripped_user %s\n",stripped_user); if (!(b = purple_find_buddy(gc->account,stripped_user))){ b = purple_buddy_new(gc->account, stripped_user, NULL); purple_blist_add_buddy(b, NULL, g, NULL); } g_free(stripped_user); } } } fclose(fd); } g_free(filename);}static char* normalize_zephyr_exposure(const char* exposure) { char *exp2 = g_strstrip(g_ascii_strup(exposure,-1)); if (!exp2) return EXPOSE_REALMVIS; if (!g_ascii_strcasecmp(exp2, EXPOSE_NONE)) return EXPOSE_NONE; if (!g_ascii_strcasecmp(exp2, EXPOSE_OPSTAFF)) return EXPOSE_OPSTAFF; if (!g_ascii_strcasecmp(exp2, EXPOSE_REALMANN)) return EXPOSE_REALMANN; if (!g_ascii_strcasecmp(exp2, EXPOSE_NETVIS)) return EXPOSE_NETVIS; if (!g_ascii_strcasecmp(exp2, EXPOSE_NETANN)) return EXPOSE_NETANN; return EXPOSE_REALMVIS;}static void zephyr_login(PurpleAccount * account){ PurpleConnection *gc; zephyr_account *zephyr; gboolean read_anyone; gboolean read_zsubs; gchar *exposure; gc = purple_account_get_connection(account); read_anyone = purple_account_get_bool(gc->account,"read_anyone",TRUE); read_zsubs = purple_account_get_bool(gc->account,"read_zsubs",TRUE); exposure = (gchar *)purple_account_get_string(gc->account, "exposure_level", EXPOSE_REALMVIS); #ifdef WIN32 username = purple_account_get_username(account);#endif gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC; gc->proto_data = zephyr=g_new0(zephyr_account,1); zephyr->account = account; /* Make sure that the exposure (visibility) is set to a sane value */ zephyr->exposure=g_strdup(normalize_zephyr_exposure(exposure)); if (purple_account_get_bool(gc->account,"use_tzc",0)) { zephyr->connection_type = PURPLE_ZEPHYR_TZC; } else { zephyr->connection_type = PURPLE_ZEPHYR_KRB4; } zephyr->encoding = (char *)purple_account_get_string(gc->account, "encoding", ZEPHYR_FALLBACK_CHARSET); purple_connection_update_progress(gc, _("Connecting"), 0, 8); /* XXX z_call_s should actually try to report the com_err determined error */ if (use_tzc(zephyr)) { pid_t pid; /* purple_connection_error(gc,"tzc not supported yet"); */ if ((pipe(zephyr->totzc) != 0) || (pipe(zephyr->fromtzc) != 0)) { purple_debug_error("zephyr", "pipe creation failed. killing\n"); exit(-1); } pid = fork(); if (pid == -1) { purple_debug_error("zephyr", "forking failed\n"); exit(-1); } if (pid == 0) { unsigned int i=0; gboolean found_ps = FALSE; gchar ** tzc_cmd_array = g_strsplit(purple_account_get_string(gc->account,"tzc_command","/usr/bin/tzc -e %s")," ",0); if (close(1) == -1) { purple_debug_error("zephyr", "stdout couldn't be closed. dying\n"); exit(-1); } if (dup2(zephyr->fromtzc[1], 1) == -1) { purple_debug_error("zephyr", "dup2 of stdout failed \n"); exit(-1); } if (close(zephyr->fromtzc[1]) == -1) { purple_debug_error("zephyr", "closing of piped stdout failed\n"); exit(-1); } if (close(0) == -1) { purple_debug_error("zephyr", "stdin couldn't be closed. dying\n"); exit(-1); } if (dup2(zephyr->totzc[0], 0) == -1) { purple_debug_error("zephyr", "dup2 of stdin failed \n"); exit(-1); } if (close(zephyr->totzc[0]) == -1) { purple_debug_error("zephyr", "closing of piped stdin failed\n"); exit(-1); } /* tzc_command should really be of the form path/to/tzc -e %s or ssh username@hostname pathtotzc -e %s -- this should not require a password, and ideally should be kerberized ssh -- or fsh username@hostname pathtotzc -e %s */ while(tzc_cmd_array[i] != NULL){ if (!g_ascii_strncasecmp(tzc_cmd_array[i],"%s",2)) { /* fprintf(stderr,"replacing %%s with %s\n",zephyr->exposure); */ tzc_cmd_array[i] = g_strdup(zephyr->exposure); found_ps = TRUE; } else { /* fprintf(stderr,"keeping %s\n",tzc_cmd_array[i]); */ } i++; } if (!found_ps) { purple_connection_error(gc,"Tzc command needs %s to set the exposure\n"); return; } execvp(tzc_cmd_array[0], tzc_cmd_array); } else { fd_set rfds; int bufsize = 2048; char *buf = (char *)calloc(bufsize, 1); char *bufcur = buf; struct timeval tv; char *ptr; int parenlevel=0; char* tempstr; int tempstridx; zephyr->tzc_pid = pid; /* wait till we have data to read from ssh */ FD_ZERO(&rfds); FD_SET(zephyr->fromtzc[ZEPHYR_FD_READ], &rfds); tv.tv_sec = 10; tv.tv_usec = 0; purple_debug_info("zephyr", "about to read from tzc\n"); select(zephyr->fromtzc[ZEPHYR_FD_READ] + 1, &rfds, NULL, NULL, NULL); FD_ZERO(&rfds); FD_SET(zephyr->fromtzc[ZEPHYR_FD_READ], &rfds); while (select(zephyr->fromtzc[ZEPHYR_FD_READ] + 1, &rfds, NULL, NULL, &tv)) { read(zephyr->fromtzc[ZEPHYR_FD_READ], bufcur, 1); bufcur++; if ((bufcur - buf) > (bufsize - 1)) { if ((buf = realloc(buf, bufsize * 2)) == NULL) { exit(-1); } else { bufcur = buf + bufsize; bufsize *= 2; } } FD_ZERO(&rfds); FD_SET(zephyr->fromtzc[ZEPHYR_FD_READ], &rfds); tv.tv_sec = 10; tv.tv_usec = 0; } /* fprintf(stderr, "read from tzc\n"); */ *bufcur = '\0'; ptr = buf; /* ignore all tzcoutput till we've received the first (*/ while (ptr < bufcur && (*ptr !='(')) { ptr++; } if (ptr >=bufcur) { purple_connection_error(gc,"invalid output by tzc (or bad parsing code)"); free(buf); return; } while(ptr < bufcur) { if (*ptr == '(') { parenlevel++; } else if (*ptr == ')') { parenlevel--; } purple_debug_info("zephyr","tzc parenlevel is %d\n",parenlevel); switch (parenlevel) { case 0: break; case 1: /* Search for next beginning (, or for the ending */ ptr++; while((*ptr != '(') && (*ptr != ')') && (ptr <bufcur)) ptr++; if (ptr >= bufcur) purple_debug_error("zephyr","tzc parsing error\n"); break; case 2: /* You are probably at (foo . bar ) or (foo . "bar") or (foo . chars) or (foo . numbers) or (foo . () ) Parse all the data between the first and last f, and move past ) */ tempstr = g_malloc0(20000); tempstridx=0; while(parenlevel >1) { ptr++; if (*ptr == '(') parenlevel++; if (*ptr == ')') parenlevel--; if (parenlevel > 1) { tempstr[tempstridx++]=*ptr; } else { ptr++; } } purple_debug_info("zephyr","tempstr parsed\n"); /* tempstr should now be a tempstridx length string containing all characters from that after the first ( to the one before the last paren ). */ /* We should have the following possible lisp strings but we don't care (tzcspew . start) (version . "something") (pid . number)*/ /* We care about 'zephyrid . "username@REALM.NAME"' and 'exposure . "SOMETHING"' */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -