⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sametime.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
}static void mw_conf_text(struct mwConference *conf,			 struct mwLoginInfo *who, const char *text) {    struct mwServiceConference *srvc;  struct mwSession *session;  struct mwPurplePluginData *pd;  PurpleConnection *gc;  char *esc;  if(! text) return;  srvc = mwConference_getService(conf);  session = mwService_getSession(MW_SERVICE(srvc));  pd = mwSession_getClientData(session);  gc = pd->gc;  esc = g_markup_escape_text(text, -1);  serv_got_chat_in(gc, CONF_TO_ID(conf), who->user_id, 0, esc, time(NULL));  g_free(esc);}static void mw_conf_typing(struct mwConference *conf,			   struct mwLoginInfo *who, gboolean typing) {  /* purple really has no good way to expose this to the user. */  const char *n = mwConference_getName(conf);  const char *w = who->user_id;  if(typing) {    DEBUG_INFO("%s in conf %s: <typing>\n", NSTR(w), NSTR(n));  } else {    DEBUG_INFO("%s in conf %s: <stopped typing>\n", NSTR(w), NSTR(n));  }}static void mw_conf_clear(struct mwServiceConference *srvc) {  ;}static struct mwConferenceHandler mw_conference_handler = {  mw_conf_invited,  mw_conf_opened,  mw_conf_closed,  mw_conf_peer_joined,  mw_conf_peer_parted,  mw_conf_text,  mw_conf_typing,  mw_conf_clear,};static struct mwServiceConference *mw_srvc_conf_new(struct mwSession *s) {  struct mwServiceConference *srvc;  srvc = mwServiceConference_new(s, &mw_conference_handler);  return srvc;}/** size of an outgoing file transfer chunk */#define MW_FT_LEN  (BUF_LONG * 2)static void ft_incoming_cancel(PurpleXfer *xfer) {  /* incoming transfer rejected or canceled in-progress */  struct mwFileTransfer *ft = xfer->data;  if(ft) mwFileTransfer_reject(ft);}static void ft_incoming_init(PurpleXfer *xfer) {  /* incoming transfer accepted */    /* - accept the mwFileTransfer     - open/create the local FILE "wb"     - stick the FILE's fp in xfer->dest_fp  */  struct mwFileTransfer *ft;  FILE *fp;  ft = xfer->data;  fp = g_fopen(xfer->local_filename, "wb");  if(! fp) {    mwFileTransfer_cancel(ft);    return;  }  xfer->dest_fp = fp;  mwFileTransfer_accept(ft);}static void mw_ft_offered(struct mwFileTransfer *ft) {  /*    - create a purple ft object    - offer it  */  struct mwServiceFileTransfer *srvc;  struct mwSession *session;  struct mwPurplePluginData *pd;  PurpleConnection *gc;  PurpleAccount *acct;  const char *who;  PurpleXfer *xfer;  /* @todo add some safety checks */  srvc = mwFileTransfer_getService(ft);  session = mwService_getSession(MW_SERVICE(srvc));  pd = mwSession_getClientData(session);  gc = pd->gc;  acct = purple_connection_get_account(gc);  who = mwFileTransfer_getUser(ft)->user;  DEBUG_INFO("file transfer %p offered\n", ft);  DEBUG_INFO(" from: %s\n", NSTR(who));  DEBUG_INFO(" file: %s\n", NSTR(mwFileTransfer_getFileName(ft)));  DEBUG_INFO(" size: %u\n", mwFileTransfer_getFileSize(ft));  DEBUG_INFO(" text: %s\n", NSTR(mwFileTransfer_getMessage(ft)));  xfer = purple_xfer_new(acct, PURPLE_XFER_RECEIVE, who);  if (xfer)  {	purple_xfer_ref(xfer);	mwFileTransfer_setClientData(ft, xfer, (GDestroyNotify) purple_xfer_unref);	xfer->data = ft;	purple_xfer_set_init_fnc(xfer, ft_incoming_init);	purple_xfer_set_cancel_recv_fnc(xfer, ft_incoming_cancel);	purple_xfer_set_request_denied_fnc(xfer, ft_incoming_cancel);	purple_xfer_set_filename(xfer, mwFileTransfer_getFileName(ft));	purple_xfer_set_size(xfer, mwFileTransfer_getFileSize(ft));	purple_xfer_set_message(xfer, mwFileTransfer_getMessage(ft));	purple_xfer_request(xfer);  }}static void ft_send(struct mwFileTransfer *ft, FILE *fp) {  guchar buf[MW_FT_LEN];  struct mwOpaque o = { .data = buf, .len = MW_FT_LEN };  guint32 rem;  PurpleXfer *xfer;  xfer = mwFileTransfer_getClientData(ft);  rem = mwFileTransfer_getRemaining(ft);  if(rem < MW_FT_LEN) o.len = rem;    if(fread(buf, (size_t) o.len, 1, fp)) {    /* calculate progress and display it */    xfer->bytes_sent += o.len;    xfer->bytes_remaining -= o.len;    purple_xfer_update_progress(xfer);    mwFileTransfer_send(ft, &o);  } else {    int err = errno;    DEBUG_WARN("problem reading from file %s: %s\n",	       NSTR(mwFileTransfer_getFileName(ft)), strerror(err));    mwFileTransfer_cancel(ft);  }}static void mw_ft_opened(struct mwFileTransfer *ft) {  /*    - get purple ft from client data in ft    - set the state to active  */  PurpleXfer *xfer;  xfer = mwFileTransfer_getClientData(ft);  if(! xfer) {    mwFileTransfer_cancel(ft);    mwFileTransfer_free(ft);    g_return_if_reached();  }  if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {    xfer->dest_fp = g_fopen(xfer->local_filename, "rb");    ft_send(ft, xfer->dest_fp);  }  }static void mw_ft_closed(struct mwFileTransfer *ft, guint32 code) {  /*    - get purple ft from client data in ft    - indicate rejection/cancelation/completion    - free the file transfer itself  */  PurpleXfer *xfer;  xfer = mwFileTransfer_getClientData(ft);  if(xfer) {    xfer->data = NULL;    if(! mwFileTransfer_getRemaining(ft)) {      purple_xfer_set_completed(xfer, TRUE);      purple_xfer_end(xfer);    } else if(mwFileTransfer_isCancelLocal(ft)) {      /* calling purple_xfer_cancel_local is redundant, since that's	 probably what triggered this function to be called */      ;    } else if(mwFileTransfer_isCancelRemote(ft)) {      /* steal the reference for the xfer */      mwFileTransfer_setClientData(ft, NULL, NULL);      purple_xfer_cancel_remote(xfer);      /* drop the stolen reference */      purple_xfer_unref(xfer);      return;    }  }  mwFileTransfer_free(ft);}static void mw_ft_recv(struct mwFileTransfer *ft,		       struct mwOpaque *data) {  /*    - get purple ft from client data in ft    - update transfered percentage    - if done, destroy the ft, disassociate from purple ft  */  PurpleXfer *xfer;  FILE *fp;  xfer = mwFileTransfer_getClientData(ft);  g_return_if_fail(xfer != NULL);  fp = xfer->dest_fp;  g_return_if_fail(fp != NULL);  /* we must collect and save our precious data */  fwrite(data->data, 1, data->len, fp);  /* update the progress */  xfer->bytes_sent += data->len;  xfer->bytes_remaining -= data->len;  purple_xfer_update_progress(xfer);  /* let the other side know we got it, and to send some more */  mwFileTransfer_ack(ft);}static void mw_ft_ack(struct mwFileTransfer *ft) {  PurpleXfer *xfer;  xfer = mwFileTransfer_getClientData(ft);  g_return_if_fail(xfer != NULL);  g_return_if_fail(xfer->watcher == 0);  if(! mwFileTransfer_getRemaining(ft)) {    purple_xfer_set_completed(xfer, TRUE);    purple_xfer_end(xfer);  } else if(mwFileTransfer_isOpen(ft)) {    ft_send(ft, xfer->dest_fp);  }}static void mw_ft_clear(struct mwServiceFileTransfer *srvc) {  ;}static struct mwFileTransferHandler mw_ft_handler = {  mw_ft_offered,  mw_ft_opened,  mw_ft_closed,  mw_ft_recv,  mw_ft_ack,  mw_ft_clear,};static struct mwServiceFileTransfer *mw_srvc_ft_new(struct mwSession *s) {  struct mwServiceFileTransfer *srvc;  GHashTable *ft_map;  ft_map = g_hash_table_new(g_direct_hash, g_direct_equal);  srvc = mwServiceFileTransfer_new(s, &mw_ft_handler);  mwService_setClientData(MW_SERVICE(srvc), ft_map,			  (GDestroyNotify) g_hash_table_destroy);  return srvc;}static void convo_data_free(struct convo_data *cd) {  GList *l;  /* clean the queue */  for(l = cd->queue; l; l = g_list_delete_link(l, l)) {    struct convo_msg *m = l->data;    if(m->clear) m->clear(m->data);    g_free(m);  }  g_free(cd);}/** allocates a convo_data structure and associates it with the    conversation in the client data slot */static void convo_data_new(struct mwConversation *conv) {  struct convo_data *cd;  g_return_if_fail(conv != NULL);  if(mwConversation_getClientData(conv))    return;  cd = g_new0(struct convo_data, 1);  cd->conv = conv;  mwConversation_setClientData(conv, cd, (GDestroyNotify) convo_data_free);}static PurpleConversation *convo_get_gconv(struct mwConversation *conv) {  struct mwServiceIm *srvc;  struct mwSession *session;  struct mwPurplePluginData *pd;  PurpleConnection *gc;  PurpleAccount *acct;  struct mwIdBlock *idb;  srvc = mwConversation_getService(conv);  session = mwService_getSession(MW_SERVICE(srvc));  pd = mwSession_getClientData(session);  gc = pd->gc;  acct = purple_connection_get_account(gc);  idb = mwConversation_getTarget(conv);  return purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,					     idb->user, acct);}static void convo_queue(struct mwConversation *conv,			enum mwImSendType type, gconstpointer data) {  struct convo_data *cd;  struct convo_msg *m;  convo_data_new(conv);  cd = mwConversation_getClientData(conv);  m = g_new0(struct convo_msg, 1);  m->type = type;  switch(type) {  case mwImSend_PLAIN:    m->data = g_strdup(data);    m->clear = g_free;    break;      case mwImSend_TYPING:  default:    m->data = (gpointer) data;    m->clear = NULL;  }  cd->queue = g_list_append(cd->queue, m);}/* Does what it takes to get an error displayed for a conversation */static void convo_error(struct mwConversation *conv, guint32 err) {  PurpleConversation *gconv;  char *tmp, *text;  struct mwIdBlock *idb;    idb = mwConversation_getTarget(conv);    tmp = mwError(err);  text = g_strconcat(_("Unable to send message: "), tmp, NULL);    gconv = convo_get_gconv(conv);  if(gconv && !purple_conv_present_error(idb->user, gconv->account, text)) {        g_free(text);    text = g_strdup_printf(_("Unable to send message to %s:"),			   (idb->user)? idb->user: "(unknown)");    purple_notify_error(purple_account_get_connection(gconv->account),		      NULL, text, tmp);  }    g_free(tmp);  g_free(text);}static void convo_queue_send(struct mwConversation *conv) {  struct convo_data *cd;  GList *l;    cd = mwConversation_getClientData(conv);  for(l = cd->queue; l; l = g_list_delete_link(l, l)) {    struct convo_msg *m = l->data;    mwConversation_send(conv, m->type, m->data);    if(m->clear) m->clear(m->data);    g_free(m);  }  cd->queue = NULL;}/**  called when a mw conversation leaves a purple conversation to     inform the purple conversation that it's unsafe to offer any *cool*     features. */static void convo_nofeatures(struct mwConversation *conv) {  PurpleConversation *gconv;  PurpleConnection *gc;  gconv = convo_get_gconv(conv);  if(! gconv) return;  gc = purple_conversation_get_gc(gconv);  if(! gc) return;  purple_conversation_set_features(gconv, gc->flags);}/** called when a mw conversation and purple conversation come together,    to inform the purple conversation of what features to offer the    user */static void convo_features(struct mwConversation *conv) {  PurpleConversation *gconv;  PurpleConnectionFlags feat;  gconv = convo_get_gconv(conv);  if(! gconv) return;  feat = purple_conversation_get_features(gconv);  if(mwConversation_isOpen(conv)) {    if(mwConversation_supports(conv, mwImSend_HTML)) {      feat |= PURPLE_CONNECTION_HTML;    } else {      feat &= ~PURPLE_CONNECTION_HTML;    }    if(mwConversation_supports(conv, mwImSend_MIME)) {      feat &= ~PURPLE_CONNECTION_NO_IMAGES;    } else {      feat |= PURPLE_CONNECTION_NO_IMAGES;    }    DEBUG_INFO("conversation features set to 0x%04x\n", feat);    purple_conversation_set_features(gconv, feat);  } else {    convo_nofeatures(conv);  }}static void mw_conversation_opened(struct mwConversation *conv) {  struct mwServiceIm *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -