/* ** Amster - File sharing ** by Jacob Laursen */ #include "include/config.h" #include #include #include #include "include/mui.h" #include #include #include #include #include #include #include #include #include #include "md5.h" #include "include/protos.h" #include "include/gui.h" #include "include/info.h" #include "include/share.h" #include "include/prefs.h" #include "include/panel.h" #include "include/napster.h" #include "include/upload.h" #include "include/rexx.h" #include "amster_Cat.h" unsigned int numsongs=0, numbytes=0; BOOL sharechanged=FALSE, sharefailed=FALSE; struct FileRequester *FReqAddFiles; struct FileRequester *FReqAddDir; struct FileRequester *FReqLibrary; MUIF share_dispatch(REG(a0) struct IClass *cl, REG(a2) Object *obj, REG(a1) Msg msg) { struct shdata *data = INST_DATA(cl, obj); switch(msg->MethodID) { case OM_NEW: return(share_new(cl, obj, (APTR)msg)); case OM_DISPOSE: if (FReqAddFiles) FreeAslRequest(FReqAddFiles); if (FReqAddDir) FreeAslRequest(FReqAddDir); if (FReqLibrary) FreeAslRequest(FReqLibrary); break; case SHARE_OPEN: update_stat(data); set(obj, MUIA_Window_Open, TRUE); return(NULL); case SHARE_CLOSE: set(obj, MUIA_Window_Open, FALSE); return(NULL); case SHARE_ADD: add_shares(data); return(NULL); case SHARE_ADDDIR: add_directory(data); return(NULL); case SHARE_REMOVE: remove_shares(data, (long)(((muimsg)msg)->arg1)); return(NULL); case SHARE_SAVE: save_shares(data); return(NULL); case SHARE_SAVEAS: save_shares_as(data); return(NULL); case SHARE_LOAD: load_shares(data); return(NULL); case SHARE_LOADAS: load_shares_as(data); return(NULL); case SHARE_UPLOAD: upload_file_confirm(data, (char *)(((muimsg)msg)->arg1), (char *)(((muimsg)msg)->arg2)); return(NULL); case SHARE_NOTIFYALL: notify_shares(data); return(NULL); case SHARE_PLAY: play_share(data); return(NULL); case SHARE_ADDFILE: add_file(data, (song)(((muimsg)msg)->arg1), (char *)(((muimsg)msg)->arg2)); return(NULL); case SHARE_ADDFILEN: add_filename(data, (char *)(((muimsg)msg)->arg1)); return(NULL); } return(DoSuperMethodA(cl, obj, msg)); } MUIF sharelistdest(REG(a2) APTR pool, REG(a1) sharedata sd) { char *path; numsongs--; numbytes -= sd->size; if (gui_napon) { path = MakeWinPath(sd->title); nap_sendbuf(NAPC_REMOVESHARE, path); free(path); } free(sd); return(0); } MUIF sharelistdisp(REG(a2) char **array, REG(a1) sharedata sd) { static char size[16], md5[33], time[20], bitrate[16], freq[16]; if (sd) { *array++ = sd->title; sprintf(size, "\33r%ld", sd->size); *array++ = size; sprintf(time, "\33r%ld:%02ld", sd->time/60, sd->time%60); *array++ = time; sprintf(bitrate, "\33r%ld", sd->bitrate); *array++ = bitrate; sprintf(freq, "\33l%ld", sd->freq); *array++ = freq; strcpy(md5, sd->md5); *array = md5; } else { *array++ = (char *)MSG_LH_FILE; *array++ = (char *)MSG_LH_SIZE; *array++ = (char *)MSG_LH_TIME; *array++ = (char *)MSG_LH_BITRATE; *array++ = (char *)MSG_LH_FREQ; *array = (char *)MSG_LH_CHECKSUM; } return(0); } MUIF sharelistcomp(REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct NList_CompareMessage *ncm) { sharedata entry1 = ncm->entry1; sharedata entry2 = ncm->entry2; LONG col1 = ncm->sort_type & MUIV_NList_TitleMark_ColMask; LONG col2 = ncm->sort_type2 & MUIV_NList_TitleMark2_ColMask; ULONG result = 0; if (ncm->sort_type == MUIV_NList_SortType_None) return (0); if (col1 == 0) { if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask) result = (LONG) stricmp(entry2->title, entry1->title); else result = (LONG) stricmp(entry1->title, entry2->title); } else if (col1 == 1) { if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask) result = entry2->size - entry1->size; else result = entry1->size - entry2->size; } else if (col1 == 2) { if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask) result = entry2->time - entry1->time; else result = entry1->time - entry2->time; } else if (col1 == 3) { if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask) result = entry2->bitrate - entry1->bitrate; else result = entry1->bitrate - entry2->bitrate; } else if (col1 == 4) { if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask) result = entry2->freq - entry1->freq; else result = entry1->freq - entry2->freq; } else if (col1 == 5) { if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask) result = (LONG) stricmp(entry2->md5, entry1->md5); else result = (LONG) stricmp(entry1->md5, entry2->md5); } if ((result != 0) || (col1 == col2)) return (result); if (col2 == 0) { if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask) result = (LONG) stricmp(entry2->title, entry1->title); else result = (LONG) stricmp(entry1->title, entry2->title); } else if (col2 == 1) { if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask) result = entry2->size - entry1->size; else result = entry1->size - entry2->size; } else if (col2 == 2) { if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask) result = entry2->time - entry1->time; else result = entry1->time - entry2->time; } else if (col2 == 3) { if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask) result = entry2->bitrate - entry1->bitrate; else result = entry1->bitrate - entry2->bitrate; } else if (col2 == 4) { if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask) result = entry2->freq - entry1->freq; else result = entry1->freq - entry2->freq; } else if (col2 == 5) { if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask) result = (LONG) stricmp(entry2->md5, entry1->md5); else result = (LONG) stricmp(entry1->md5, entry2->md5); } return (result); } MUIF ShareListAppMsgFunc(REG(a2) APTR obj, REG(a1) struct AppMessage **x) { struct WBArg *ap; struct AppMessage *amsg = *x; int i; static char buf[256]; for (ap=amsg->am_ArgList, i=0; iam_NumArgs; i++, ap++) { NameFromLock(ap->wa_Lock, buf, sizeof(buf)); AddPart(buf, ap->wa_Name, sizeof(buf)); DoMethod(gui->shwin, SHARE_ADDFILEN, buf); } return(0); } ULONG share_new(struct IClass *cl, Object *obj, struct opSet *msg) { static const struct Hook sharelistdispHook = { {NULL, NULL}, &sharelistdisp, NULL, NULL }; static const struct Hook sharelistcompHook = { {NULL, NULL}, &sharelistcomp, NULL, NULL }; static const struct Hook sharelistdestHook = { {NULL, NULL}, &sharelistdest, NULL, NULL }; static const struct Hook ShareListAppMsgHook = { {NULL, NULL}, &ShareListAppMsgFunc, NULL, NULL }; struct shdata *data; Object *list, *stat, *addbut, *adddirbut, *rembut, *remallbut; if (obj = (Object *)DoSuperNew(cl, obj, MUIA_HelpNode, "sharing", MUIA_Window_ID, MAKE_ID('S','H','A','R'), MUIA_Window_Title, MSG_SHARE_TITLE, MUIA_Window_AppWindow, TRUE, WindowContents, VGroup, MUIA_HelpNode, "sharing", Child, stat = TextObject, TextFrame, MUIA_Background, MUII_TextBack, MUIA_Text_PreParse, "\33c", End, Child, list = NListviewObject, MUIA_NListview_NList, NListObject, InputListFrame, MUIA_NList_Title, TRUE, MUIA_NList_Format, "BAR, BAR, BAR, BAR, BAR", MUIA_NList_DisplayHook, &sharelistdispHook, MUIA_NList_CompareHook2, &sharelistcompHook, MUIA_NList_DestructHook, &sharelistdestHook, MUIA_NList_MultiSelect, MUIV_NList_MultiSelect_Default, MUIA_NList_MinColSortable, 0, MUIA_CycleChain, 1, End, End, Child, HGroup, Child, addbut = SimpleButton(MSG_SHARE_ADD_GAD ), Child, adddirbut = SimpleButton(MSG_SHARE_ADDRECURSIVE_GAD), Child, rembut = SimpleButton(MSG_SHARE_REMOVE_GAD ), Child, remallbut = SimpleButton(MSG_SHARE_REMOVEALL_GAD ), End, End, TAG_MORE, msg->ops_AttrList)) { data = INST_DATA(cl,obj); data->list = list; data->stat = stat; /* Default sort */ DoMethod(list, MUIM_Set, MUIA_NList_TitleMark, 0); DoMethod(list, MUIM_NList_Sort3, 0, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_Both); /* Window notify */ DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, gui->iconpanel, 1, PANEL_CLOSESHARE); /* List notifies */ DoMethod(list, MUIM_Notify, MUIA_NList_DoubleClick, MUIV_EveryTime, obj, 1, SHARE_PLAY); DoMethod(list, MUIM_Notify, MUIA_NList_TitleClick, MUIV_EveryTime, list, 4, MUIM_NList_Sort3, MUIV_TriggerValue, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_Both); DoMethod(list, MUIM_Notify, MUIA_NList_TitleClick2, MUIV_EveryTime, list, 4, MUIM_NList_Sort3, MUIV_TriggerValue, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_2); DoMethod(list, MUIM_Notify, MUIA_NList_SortType, MUIV_EveryTime, list, 3, MUIM_Set, MUIA_NList_TitleMark, MUIV_TriggerValue); DoMethod(list, MUIM_Notify, MUIA_NList_SortType2, MUIV_EveryTime, list, 3, MUIM_Set, MUIA_NList_TitleMark2, MUIV_TriggerValue); DoMethod(list, MUIM_Notify, MUIA_AppMessage, MUIV_EveryTime, list, 3, MUIM_CallHook, &ShareListAppMsgHook, MUIV_TriggerValue); /* Button notifies */ DoMethod(addbut, MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, SHARE_ADD ); DoMethod(adddirbut, MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, SHARE_ADDDIR ); DoMethod(rembut, MUIM_Notify, MUIA_Pressed, FALSE, obj, 2, SHARE_REMOVE, 0); DoMethod(remallbut, MUIM_Notify, MUIA_Pressed, FALSE, obj, 2, SHARE_REMOVE, 1); /* Allocate file requesters */ FReqAddFiles = AllocAslRequestTags(ASL_FileRequest, ASLFR_TitleText, MSG_SHARE_ADD_REQ, ASLFR_InitialPattern, (ULONG)"#?.mp(2|3)", ASLFR_InitialDrawer, (ULONG)prf->dlpath, ASLFR_DoPatterns, TRUE, ASLFR_DoMultiSelect, TRUE, ASLFR_RejectIcons, TRUE, TAG_DONE); FReqAddDir = AllocAslRequestTags(ASL_FileRequest, ASLFR_TitleText, MSG_SHARE_ADDDIR_REQ, ASLFR_InitialDrawer, (ULONG)prf->dlpath, ASLFR_DrawersOnly, TRUE, TAG_DONE); FReqLibrary = AllocAslRequestTags(ASL_FileRequest, ASLFR_InitialFile, "Amster.shares", ASLFR_InitialDrawer, "PROGDIR:", ASLFR_RejectIcons, TRUE, TAG_DONE); return((ULONG)obj); } return(0); } /* Private functions */ void add_filename(struct shdata *data, char *fname) { sharedata sd; struct FileInfoBlock *fib; BPTR lock; if (!(fib = AllocMem(sizeof(*fib), MEMF_PUBLIC))) return; if (sd = malloc(sizeof(_sharedata))) { memset(sd, 0, sizeof(_sharedata)); strcpy(sd->title, fname); if (lock = Lock(fname, ACCESS_READ)) { if (Examine(lock, fib)) { sd->size = fib->fib_Size; if (NameFromLock(lock, sd->title, 255)) { if (fib->fib_DirEntryType < 0) add_shareinfo(data, sd, lock); else if (fib->fib_DirEntryType > 0) { add_recursive(data, sd, lock, sd->title); UnLock(lock); } } else UnLock(lock); } } } FreeMem(fib, sizeof(*fib)); } void add_file(struct shdata *data, song sdl, char *fname) { sharedata sd; struct FileInfoBlock *fib; BPTR lock; if (sd = malloc(sizeof(_sharedata))) { memset(sd, 0, sizeof(_sharedata)); if (fib = AllocMem(sizeof(*fib), MEMF_PUBLIC)) { if (lock = Lock(fname, ACCESS_READ)) { NameFromLock(lock, sd->title, 255); UnLock(lock); } FreeMem(fib, sizeof(*fib)); } if(!sd->title) strcpy(sd->title, fname); strncpy(sd->md5, sdl->md5, 32); sd->size = sdl->size; sd->bitrate = sdl->bit; sd->freq = sdl->freq; sd->time = sdl->time; DoMethod(data->list, MUIM_NList_InsertSingle, sd, MUIV_NList_Insert_Sorted); numsongs++; numbytes += sd->size; sharechanged = TRUE; update_stat(data); if(gui_napon) nap_notifyshare(sd); } return; } void add_shares(struct shdata *data) { sharedata sd; BPTR lock; struct FileInfoBlock *fib; int i; if (FReqAddFiles) { if (AslRequestTags(FReqAddFiles, ASLFR_InitialFile, NULL, TAG_DONE)) { if (fib = AllocMem(sizeof(*fib), MEMF_PUBLIC)) { for (i=0; ifr_NumArgs; i++) { if (sd = malloc(sizeof(_sharedata))) { memset(sd, 0, sizeof(_sharedata)); strcpy(sd->title, FReqAddFiles->fr_Drawer); AddPart(sd->title, FReqAddFiles->fr_ArgList[i].wa_Name, 255); if (lock = Lock(sd->title, ACCESS_READ)) { if (Examine(lock, fib)) { sd->size = fib->fib_Size; if (NameFromLock(lock, sd->title, 255)) { if (fib->fib_DirEntryType < 0) add_shareinfo(data, sd, lock); else if (fib->fib_DirEntryType > 0) { add_recursive(data, sd, lock, sd->title); UnLock(lock); } } else UnLock(lock); } } } } FreeMem(fib, sizeof(*fib)); } } if (sharefailed) { MUI_Request(gui->app, gui->shwin, 0L, (char *)MSG_ERROR_TITLE, (char *)MSG_OK_GAD, (char *)MSG_SHARE_ADDFAILED); sharefailed = FALSE; } } } void add_directory(struct shdata *data) { sharedata sd; BPTR lock; struct FileInfoBlock *fib; if (FReqAddDir) { if (AslRequestTags(FReqAddDir, TAG_DONE)) { if (fib = AllocMem(sizeof(*fib), MEMF_PUBLIC)) { if (sd = malloc(sizeof(_sharedata))) { memset(sd, 0, sizeof(_sharedata)); strcpy(sd->title, FReqAddDir->fr_Drawer); if (lock = Lock(sd->title, ACCESS_READ)) { if (Examine(lock, fib)) { sd->size = fib->fib_Size; if (NameFromLock(lock, sd->title, 255)) { if (fib->fib_DirEntryType > 0) { add_recursive(data, sd, lock, sd->title); UnLock(lock); } } else UnLock(lock); } } } FreeMem(fib, sizeof(*fib)); } } if (sharefailed) { MUI_Request(gui->app, gui->shwin, 0L, (char *)MSG_ERROR_TITLE, (char *)MSG_OK_GAD, (char *)MSG_SHARE_ADDFAILED); sharefailed = FALSE; } } } void add_recursive(struct shdata *data, sharedata sd, BPTR dirlock, const char *dirname) { ULONG namelen; long len; struct ExAllControl *eac; struct ExAllData *ead; APTR eadata; BOOL more; char *name; BPTR lock; struct FileInfoBlock *fib; const long buffersize = 4096; if (dirlock) { namelen = strlen(dirname); eac = AllocDosObject(DOS_EXALLCONTROL, NULL); if (eac) { eac->eac_LastKey = 0; eac->eac_MatchString = 0; eac->eac_MatchFunc = 0; eadata = malloc(buffersize); if (eadata) { do { more = ExAll(dirlock, eadata, buffersize, ED_TYPE, eac); if (eac->eac_Entries > 0) { ead = eadata; do { len = namelen + strlen(ead->ed_Name); name = (char *)malloc(len+5); if (name) { strcpy(name, dirname); if (AddPart(name, ead->ed_Name, len+5)) { if (ead->ed_Type > 0) { lock = Lock(name, ACCESS_READ); if (lock) { add_recursive(data, sd, lock, name); UnLock(lock); } } else if (ead->ed_Type < 0) { if (sd = malloc(sizeof(_sharedata))) { memset(sd, 0, sizeof(_sharedata)); strcpy(sd->title, name); if (fib = AllocMem(sizeof(*fib), MEMF_PUBLIC)) { lock = Lock(name, ACCESS_READ); if (lock) { if (Examine(lock, fib)) { sd->size = fib->fib_Size; add_shareinfo(data, sd, lock); } } } FreeMem(fib, sizeof(*fib)); } } } free(name); } ead = ead->ed_Next; } while(ead); } if ((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES)) break; if (eac->eac_Entries == 0) continue; } while (more); free(eadata); } FreeDosObject(DOS_EXALLCONTROL, eac); } } } void add_shareinfo(struct shdata *data, sharedata sd, BPTR lock) { unsigned int m_id, m_layer, m_bit, m_freq, m_mode; APTR buffer; BPTR fh; int i=0, j=0, len, total, col; long vbrbytes = 0, vbrframes = 0, vbr = 0; BOOL header = FALSE; int badhdr[10]; char *suffix; sharedata sdtmp; ULONG tmp; md5_state_t state; md5_byte_t digest[16]; int di; /* MP3 information source: http://mp3tech.free.fr/programmers/frame_header.html */ int mp3_bitrates[14][6] = { /* V1L1,V1L2,V1L3,V2L1,V2L2,V2L3 */ { 32, 32, 32, 32, 8, 8 }, { 64, 48, 40, 48, 16, 16 }, { 96, 56, 48, 56, 24, 24 }, { 128, 64, 56, 64, 32, 32 }, { 160, 80, 64, 80, 40, 40 }, { 192, 96, 80, 96, 48, 48 }, { 224, 112, 96, 112, 56, 56 }, { 256, 128, 112, 128, 64, 64 }, { 288, 160, 128, 144, 80, 80 }, { 320, 192, 160, 160, 96, 96 }, { 352, 224, 192, 176, 112, 112 }, { 384, 256, 224, 192, 128, 128 }, { 416, 320, 256, 224, 144, 144 }, { 448, 384, 320, 256, 160, 160 } }; /* V1 = MPEG Version 1 V2 = MPEG Version 2 and Version 2.5 L1 = Layer I L2 = Layer II L3 = Layer III */ int mp3_frequencies[3][3] = { /* MPEG1, MPEG2, MPEG2.5 */ { 44100, 22050, 11025 }, { 48000, 24000, 12000 }, { 32000, 16000, 8000 } }; if (IsIn(sd->title, '"') || IsIn(sd->title, '\\')) { gui_debugf((char *)MSG_SHARE_ILLEGALCHARS, sd->title); sharefailed = TRUE; UnLock(lock); return; } suffix = sd->title + strlen(sd->title) - 4; if (stricmp(suffix, ".mp3") != 0 && stricmp(suffix, ".mp2") != 0) { gui_debugf((char *)MSG_SHARE_INVALIDEXTENSION, sd->title); sharefailed = TRUE; UnLock(lock); return; } GetAttr(MUIA_NList_Entries, data->list, &tmp); total = tmp; while (i < total) { DoMethod(data->list, MUIM_NList_GetEntry, i, &sdtmp); if (sdtmp) if (strcmp(sd->title, sdtmp->title) == 0) { gui_debugf((char *)MSG_SHARE_EXISTS, sd->title); sharefailed = TRUE; UnLock(lock); return; } i++; } if (fh = OpenFromLock(lock)) { if (buffer = AllocMem(300032, MEMF_ANY)) { md5_init(&state); len = Read(fh, buffer, 300032); if (len > 0) { md5_append(&state, (const md5_byte_t *)buffer, len); md5_finish(&state, digest); for (di = 0; di < 16; ++di) sprintf(sd->md5+di*2, "%02x", digest[di]); /* Only check first 128 kB for valid MP3 header */ if (len > 128*1024) len = 128*1024; /* Check for VBR */ for (i=0; i> 1)) { j++; vbrframes = *((unsigned long *)buffer+j/4); vbrbytes = *((unsigned long *)buffer+(j+4)/4); j += 7; } if (vbrframes > 0 && vbrbytes > 0) vbr = ((vbrbytes / vbrframes) * 1000) / 3265; break; } } i = j; if (stcd_i(buffer, badhdr) == 8 && i < 417) i = 417; /* Work-around for "MpegDJ Encoder" bug */ while (!header && i= 224) { /* MPEG Audio version ID 00 - MPEG Version 2.5 (later extension of MPEG 2) 01 - reserved 10 - MPEG Version 2 (ISO/IEC 13818-3) 11 - MPEG Version 1 (ISO/IEC 11172-3) */ m_id = 3 - ((*((char *)buffer+i+1) & 24)>>3); if (m_id == 3) m_id = 1; /* Layer description 00 - reserved 01 - Layer III 10 - Layer II 11 - Layer I */ m_layer = 4 - ((*((char *)buffer+i+1) & (2+4))>>1); m_bit = (*((char *)buffer+i+2) & (16+32+64+128))>>4; m_freq = (*((char *)buffer+i+2) & (4+8))>>2; /* Channel Mode 00 - Stereo 01 - Joint stereo (Stereo) 10 - Dual channel (2 mono channels) 11 - Single channel (Mono) */ m_mode = (*((char *)buffer+i+3) & (64+128))>>6; /* printf("version %d layer %d mode %d bit %ld freq %ld\n", m_id+1, m_layer, m_mode, m_bit, m_freq); */ col = m_layer-1; if (m_id == 1) col=col+3; if (m_bit>0 && m_bit<15 && m_freq < 3 && m_layer < 4 && m_id != 2) { header = TRUE; sd->freq = mp3_frequencies[m_freq][m_id]; if (vbr > 0) sd->bitrate = vbr; else sd->bitrate = mp3_bitrates[m_bit-1][col]; if (m_layer == 2) { /* Sanity checks */ if ((sd->bitrate == 32 || sd->bitrate == 48 || sd->bitrate == 46 || sd->bitrate == 80) && m_mode != 3) header = FALSE; if ((sd->bitrate == 224 || sd->bitrate == 256 || sd->bitrate == 320 || sd->bitrate == 384) && m_mode == 3) header = FALSE; } sd->time = (sd->size-i)/(sd->bitrate*125); /* 'i' is the length of ID3v2 tag. ID3v1 size is always 128 bytes, so it's not worth the overhead to check for this. 128 bytes of a 128 kbps MP3 = 0.000008 seconds! */ } } } i++; } } FreeMem(buffer, 300032); } Close(fh); if (header) { DoMethod(data->list, MUIM_NList_InsertSingle, sd, MUIV_NList_Insert_Sorted); numsongs++; numbytes += sd->size; sharechanged = TRUE; update_stat(data); if(gui_napon) nap_notifyshare(sd); } else { gui_debugf((char *)MSG_SHARE_ADDERROR, sd->title, sd->size, sd->bitrate, sd->freq); sharefailed = TRUE; } } else UnLock(lock); } void notify_shares(struct shdata *data) { sharedata sd; u_long tmp; int i, total; if (!gui_napon) return; GetAttr(MUIA_NList_Entries, data->list, &tmp); total = tmp; if (total > 0) { gui_stat((char *)MSG_STATUS2_NOTIFYALL); for (i=0; ilist, MUIM_NList_GetEntry, i, &sd); if (!sd) break; nap_notifyshare(sd); } } } void remove_shares(struct shdata *data, long t) { sharedata sd; u_long tmp; int total; GetAttr(MUIA_NList_Entries, data->list, &tmp); total = tmp; if (total == 0) return; switch(t) { case 0: /* Remove marked */ set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_Visual); DoMethod(data->list, MUIM_NList_Remove, MUIV_NList_Remove_Selected); update_stat(data); set(data->list,MUIA_NList_Quiet, MUIV_NList_Quiet_None); break; case 1: /* Remove all */ set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_Visual); for (;;) { DoMethod(data->list, MUIM_NList_GetEntry, 0, &sd); if (!sd) break; DoMethod(data->list, MUIM_NList_Remove, MUIV_NList_Remove_First); } update_stat(data); set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_None); break; } sharechanged = TRUE; } void save_shares(struct shdata *data) { sharedata sd; int i; BPTR fh; char buf[512], *tmp; strcpy(buf, FReqLibrary->fr_Drawer); AddPart(buf, FReqLibrary->fr_File, 511); fh = Open(buf, MODE_NEWFILE); if (!fh) return; for(i=0; ; i++) { DoMethod(data->list, MUIM_NList_GetEntry, i, &sd); if (!sd) break; tmp = strrep(sd->title, "\"", "*\""); sprintf(buf, "\"%s\" %s %ld %ld %ld %ld\n", tmp, sd->md5, sd->size, sd->bitrate, sd->freq, sd->time); free(tmp); Write(fh, buf, strlen(buf)); /* Should be buffered, check FWrite */ } Close(fh); sharechanged = FALSE; } void save_shares_as(struct shdata *data) { if (FReqLibrary) { if (AslRequestTags(FReqLibrary, ASLFR_TitleText, MSG_SHARE_SAVEAS, ASLFR_DoSaveMode, TRUE, TAG_DONE)) { save_shares(data); } } } void load_shares(struct shdata *data) { sharedata sd; int bufsize = 0, line = 0; BPTR fh, lock; char buf[512], sharefile[512]; struct FileInfoBlock *fib; LONG argarray[] = { NULL, NULL, NULL, NULL, NULL, NULL }; UBYTE *argstr = "PATH/A,MD5/A,SIZE/A/N,BITRATE/A/N,FREQUENCY/A/N,TIME/A/N"; struct RDArgs *rdargs; remove_shares(data, 1); strcpy(sharefile, FReqLibrary->fr_Drawer); AddPart(sharefile, FReqLibrary->fr_File, 511); if (!(lock = Lock(sharefile, ACCESS_READ))) return; if (fib = AllocMem(sizeof(*fib), MEMF_PUBLIC)) { if (Examine(lock, fib)) bufsize = fib->fib_Size; FreeMem(fib, sizeof(*fib)); } if (bufsize > 0) { if (fh = OpenFromLock(lock)) { set(data->list,MUIA_NList_Quiet, MUIV_NList_Quiet_Visual); while (FGets(fh, buf, 512)) { line++; if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) { rdargs->RDA_Buffer = NULL; rdargs->RDA_Source.CS_Buffer = buf; rdargs->RDA_Source.CS_Length = strlen(buf); if (ReadArgs(argstr, argarray, rdargs)) { sd = malloc(sizeof(_sharedata)); strcpy(sd->title, (char *)argarray[ ARG_PATH ]); strcpy(sd->md5, (char *)argarray[ ARG_MD5 ]); sd->size = *((long *)argarray[ ARG_SIZE ]); sd->bitrate = *((long *)argarray[ ARG_BITRATE ]); sd->freq = *((long *)argarray[ ARG_FREQ ]); sd->time = *((long *)argarray[ ARG_TIME ]); DoMethod(data->list, MUIM_NList_InsertSingle, sd, MUIV_NList_Insert_Bottom); numsongs++; numbytes += sd->size; if (gui_napon) nap_notifyshare(sd); FreeArgs(rdargs); } else gui_debugf("Error parsing '%s' line #%ld\n", sharefile, line); FreeDosObject(DOS_RDARGS, rdargs); } } set(data->list, MUIA_NList_Quiet, MUIV_NList_Quiet_None); update_stat(data); Close(fh); } } UnLock(lock); sharechanged = FALSE; } void load_shares_as(struct shdata *data) { if (FReqLibrary) { if (AslRequestTags(FReqLibrary, ASLFR_TitleText, MSG_SHARE_LOADAS, TAG_DONE)) { load_shares(data); } } } void update_stat(struct shdata *data) { static char buf[100], totalsize[8]; char descriptor[16]; unsigned long number, tempnumber; if (numbytes >= (1024*1024*1024)) { strcpy(descriptor, MSG_SHARE_STAT_GB); tempnumber = numbytes/1024/1024*10/1024; number = tempnumber/10; tempnumber = tempnumber-(number*10); sprintf(totalsize,"%d.%d", number, tempnumber); } else if (numbytes >= (1024*1024)) { strcpy(descriptor, MSG_SHARE_STAT_MB); tempnumber = numbytes/1024*10/1024; number = tempnumber/10; tempnumber = tempnumber-(number*10); sprintf(totalsize, "%d.%d", number, tempnumber); } else { strcpy(descriptor, MSG_SHARE_STAT_KB); number = numbytes/1024; sprintf(totalsize, "%d", number); } sprintf(buf, MSG_SHARE_STAT_TMP, numsongs, totalsize, descriptor); set(data->stat, MUIA_Text_Contents, buf); } void play_share(struct shdata *data) { sharedata sd; char buf[1024], *command; DoMethod(data->list, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &sd); if (sd) { if (prf->scripts[PRFE_PLAYMP3]) { sprintf(buf, "Run <>NIL: %s", prf->scripts[PRFE_PLAYMP3]); command = strrep(buf, "%f", sd->title); Execute(command, 0, 0); free(command); } } } void upload_req(char *user, char *fname) { DoMethod(gui->shwin, SHARE_UPLOAD, user, fname); } void upload_file_confirm(struct shdata *data, char *user, char *fname) /* Continued from upload_req() */ { sharedata sd; song s; int i=0, total; ULONG tmp; BOOL found = FALSE; char *path; GetAttr(MUIA_NList_Entries, data->list, &tmp); total = tmp; gui_debugf((char *)MSG_SHARE_REQFILE, user, fname); while (ilist, MUIM_NList_GetEntry, i, &sd); if (sd) { path = MakeWinPath(sd->title); if (strcmp(path, fname) == 0) found = TRUE; free(path); } i++; } if (!found) { gui_debug((char *)MSG_SHARE_NOTFOUND); return; } s = malloc(sizeof(_song)); if (!s) return; memset(s, 0, sizeof(_song)); s->title = strdup(sd->title); s->md5 = strdup(sd->md5); s->size = sd->size; s->bit = sd->bitrate; s->freq = sd->freq; s->time = sd->time; s->user = strdup(user); /* At this point we don't know IP and link speed - can't complete the struct */ ul_addq(s); } void nap_notifyshare(sharedata sd) { char *path, *suffix; /* In case invalid files were added manually or with an earlier version */ if (IsIn(sd->title, '"') || IsIn(sd->title, '\\')) { gui_debugf((char *)MSG_SHARE_ILLEGALCHARS, sd->title); return; } suffix = sd->title + strlen(sd->title) - 4; if (stricmp(suffix, ".mp3") != 0 && stricmp(suffix, ".mp2") != 0) { gui_debugf((char *)MSG_SHARE_INVALIDEXTENSION, sd->title); return; } path = MakeWinPath(sd->title); sprintf(nap_buf, "\"%s\" %s %ld %ld %ld %ld", path, sd->md5, sd->size, sd->bitrate, sd->freq, sd->time); free(path); nap_send(NAPC_NOTIFYSHARE); } char *strrep(char *str1, char *old_str, char *new_str) { char *str; int len, i; if (!(str = malloc(1024))) return str1; str[0] = '\0'; for (i=0; i