message.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. /*
  2. JAMLIB - A JAM subroutine library
  3. Copyright (C) 1999 Björn Stenberg
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. Changes made by Johan Billing 2000-04-16:
  16. - Changed source to use feof() instead of errno == EPASTEOF
  17. - Changed source to use structrw to read and write structures
  18. - Added JAM_AddEmptyMessage()
  19. - Added error messages JAM_NO_MESSAGE and JAM_CORRUPT_MSG for
  20. JAM_ReadMsgHeader()
  21. - #includes stdlib.h instead of malloc.h and memory.h
  22. - Fixed a bug that caused JAM_AddMessage() to fail when trying to
  23. add an empty message to the messagebase under Linux.
  24. Backported changes from JAMLIB 1.4.7 made by Johan Billing 2003-10-26
  25. - Fixed memory leaks that would occur if JAM_ReadMsgHeader() failed
  26. - Added JAM_DeleteMessage()
  27. Other changes made by Johan Billing 2003-10-26
  28. - Fixed comparison between signed and unsigned variable in JAM_AddMessage()
  29. - Improved handling of ActiveMsgs counter. JAM_AddMessage() now only
  30. increases ActiveMsgs if the added message does not have JAM_MSG_DELETED set.
  31. JAM_ChangeMsgHeader() decreases ActiveMsgs if JAM_MSG_DELETED is set and the
  32. message wasn't already deleted. JAM_DeleteMessage() now only decreases
  33. ActiveMsgs if the message wasn't already deleted.
  34. */
  35. /***********************************************************************
  36. **
  37. ** Message.C -- Message handling
  38. **
  39. ** Author: Bj”rn Stenberg ([email protected])
  40. **
  41. ***********************************************************************/
  42. #include <stdio.h>
  43. #include <errno.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include "jam.h"
  47. #include "structrw.h"
  48. /***********************************************************************
  49. **
  50. ** JAM_ReadMsgHeader - Read message header
  51. **
  52. ***********************************************************************/
  53. int JAM_ReadMsgHeader( s_JamBase* Base_PS,
  54. uint32_t MsgNo_I,
  55. s_JamMsgHeader* Header_PS,
  56. s_JamSubPacket** SubfieldPack_PPS )
  57. {
  58. s_JamIndex Index_S;
  59. if ( !Base_PS || !Header_PS )
  60. return JAM_BAD_PARAM;
  61. /* find index record */
  62. if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ), SEEK_SET ) ) {
  63. Base_PS->Errno_I = errno;
  64. return JAM_IO_ERROR;
  65. }
  66. /* read index record */
  67. if ( 1 > freadjamindex(Base_PS->IdxFile_PS,&Index_S) ) {
  68. Base_PS->Errno_I = errno;
  69. return JAM_IO_ERROR;
  70. }
  71. /* message is not there */
  72. if(Index_S.HdrOffset == 0xffffffff && Index_S.UserCRC == 0xffffffff)
  73. {
  74. return JAM_NO_MESSAGE;
  75. }
  76. /* find header */
  77. if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) {
  78. Base_PS->Errno_I = errno;
  79. return JAM_IO_ERROR;
  80. }
  81. /* read header */
  82. if ( 1 > freadjammsgheader(Base_PS->HdrFile_PS,Header_PS) ) {
  83. Base_PS->Errno_I = errno;
  84. return JAM_IO_ERROR;
  85. }
  86. /* are Subfields requested? */
  87. if ( SubfieldPack_PPS && Header_PS->SubfieldLen ) {
  88. s_JamSubPacket* SubPacket_PS;
  89. s_JamSubfield Subfield_S;
  90. char* Buf_PC;
  91. char* Ptr_PC;
  92. char* Roof_PC;
  93. int BufSize_I = Header_PS->SubfieldLen;
  94. Buf_PC = (void*) malloc( BufSize_I );
  95. if ( !Buf_PC )
  96. return JAM_NO_MEMORY;
  97. /* read all subfields */
  98. if ( 1 > fread( Buf_PC, BufSize_I, 1, Base_PS->HdrFile_PS ) ) {
  99. Base_PS->Errno_I = errno;
  100. free (Buf_PC);
  101. return JAM_IO_ERROR;
  102. }
  103. SubPacket_PS = JAM_NewSubPacket();
  104. if ( !SubPacket_PS ) {
  105. free (Buf_PC);
  106. return JAM_NO_MEMORY;
  107. }
  108. Roof_PC = Buf_PC + BufSize_I;
  109. /* cut out the subfields */
  110. for ( Ptr_PC = Buf_PC;
  111. Ptr_PC < Roof_PC;
  112. Ptr_PC += Subfield_S.DatLen + SIZE_JAMSAVESUBFIELD ) {
  113. int Status_I;
  114. getjamsubfield(Ptr_PC,&Subfield_S);
  115. if((char *)Subfield_S.Buffer + Subfield_S.DatLen > Roof_PC) {
  116. JAM_DelSubPacket( SubPacket_PS );
  117. free (Buf_PC);
  118. return JAM_CORRUPT_MSG;
  119. }
  120. Status_I = JAM_PutSubfield( SubPacket_PS, &Subfield_S );
  121. if ( Status_I ) {
  122. JAM_DelSubPacket( SubPacket_PS );
  123. free (Buf_PC);
  124. return Status_I;
  125. }
  126. }
  127. free( Buf_PC );
  128. *SubfieldPack_PPS = SubPacket_PS;
  129. }
  130. else
  131. if ( SubfieldPack_PPS )
  132. /* fields requested but none found */
  133. /* return an empty packet */
  134. *SubfieldPack_PPS = JAM_NewSubPacket();
  135. return 0;
  136. }
  137. /***********************************************************************
  138. **
  139. ** JAM_ReadMsgText - Read message text
  140. **
  141. ***********************************************************************/
  142. int JAM_ReadMsgText( s_JamBase* Base_PS,
  143. uint32_t Offset_I,
  144. uint32_t Length_I,
  145. char* Buffer_PC )
  146. {
  147. if ( !Base_PS || !Buffer_PC )
  148. return JAM_BAD_PARAM;
  149. if ( !Length_I )
  150. return 0;
  151. if ( fseek( Base_PS->TxtFile_PS, Offset_I, SEEK_SET ) ) {
  152. Base_PS->Errno_I = errno;
  153. return JAM_IO_ERROR;
  154. }
  155. if ( 1 > fread( Buffer_PC, Length_I, 1, Base_PS->TxtFile_PS ) ) {
  156. Base_PS->Errno_I = errno;
  157. return JAM_IO_ERROR;
  158. }
  159. return 0;
  160. }
  161. /***********************************************************************
  162. **
  163. ** JAM_ChangeMsgHeader - Change a message header
  164. **
  165. ***********************************************************************/
  166. int JAM_ChangeMsgHeader( s_JamBase* Base_PS,
  167. uint32_t MsgNo_I,
  168. s_JamMsgHeader* Header_PS )
  169. {
  170. s_JamBaseHeader BaseHeader_S;
  171. s_JamMsgHeader OldHeader_S;
  172. s_JamIndex Index_S;
  173. int Status_I;
  174. if ( !Base_PS )
  175. return JAM_BAD_PARAM;
  176. if ( !Base_PS->Locked_I )
  177. return JAM_NOT_LOCKED;
  178. /* read message base header */
  179. Status_I = JAM_ReadMBHeader( Base_PS, &BaseHeader_S );
  180. if ( Status_I )
  181. return Status_I;
  182. /* find index record */
  183. if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ),
  184. SEEK_SET ) ) {
  185. Base_PS->Errno_I = errno;
  186. return JAM_IO_ERROR;
  187. }
  188. /* read index record */
  189. if ( 1 > freadjamindex(Base_PS->IdxFile_PS,&Index_S) ) {
  190. Base_PS->Errno_I = errno;
  191. return JAM_IO_ERROR;
  192. }
  193. /* find header */
  194. if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) {
  195. Base_PS->Errno_I = errno;
  196. return JAM_IO_ERROR;
  197. }
  198. /* read old message header */
  199. if ( 1 > freadjammsgheader( Base_PS->HdrFile_PS, &OldHeader_S ) ) {
  200. Base_PS->Errno_I = errno;
  201. return JAM_IO_ERROR;
  202. }
  203. /* find header */
  204. if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) {
  205. Base_PS->Errno_I = errno;
  206. return JAM_IO_ERROR;
  207. }
  208. /* write header */
  209. if ( 1 > fwritejammsgheader(Base_PS->HdrFile_PS,Header_PS) ) {
  210. Base_PS->Errno_I = errno;
  211. return JAM_IO_ERROR;
  212. }
  213. if( ( Header_PS->Attribute & JAM_MSG_DELETED ) && !(OldHeader_S.Attribute & JAM_MSG_DELETED) ) {
  214. /* message is deleted now but wasn't before */
  215. BaseHeader_S.ActiveMsgs--;
  216. }
  217. Status_I = JAM_WriteMBHeader( Base_PS, &BaseHeader_S );
  218. if ( Status_I )
  219. return Status_I;
  220. return 0;
  221. }
  222. /***********************************************************************
  223. **
  224. ** JAM_AddMessage - Add a message to a message base
  225. **
  226. ***********************************************************************/
  227. int JAM_AddMessage( s_JamBase* Base_PS,
  228. s_JamMsgHeader* Header_PS,
  229. s_JamSubPacket* SubPack_PS,
  230. char* Text_PC,
  231. uint32_t TextLen_I )
  232. {
  233. s_JamBaseHeader BaseHeader_S;
  234. s_JamIndex Index_S;
  235. long Offset_I;
  236. int Status_I;
  237. uint32_t TotLen_I;
  238. if ( !Base_PS )
  239. return JAM_BAD_PARAM;
  240. if ( !Base_PS->Locked_I )
  241. return JAM_NOT_LOCKED;
  242. /* read message base header */
  243. Status_I = JAM_ReadMBHeader( Base_PS, &BaseHeader_S );
  244. if ( Status_I )
  245. return Status_I;
  246. /*
  247. ** Add text if any
  248. */
  249. Header_PS->TxtOffset = 0;
  250. Header_PS->TxtLen = 0;
  251. if(Text_PC && TextLen_I!=0)
  252. {
  253. /* go to end of text file */
  254. if ( fseek( Base_PS->TxtFile_PS, 0, SEEK_END ) ) {
  255. Base_PS->Errno_I = errno;
  256. return JAM_IO_ERROR;
  257. }
  258. /* store text offset (for header) */
  259. Offset_I = ftell( Base_PS->TxtFile_PS );
  260. if ( Offset_I == -1 ) {
  261. Base_PS->Errno_I = errno;
  262. return JAM_IO_ERROR;
  263. }
  264. Header_PS->TxtOffset = Offset_I;
  265. Header_PS->TxtLen = TextLen_I;
  266. /* write text */
  267. if ( 1 > fwrite( Text_PC, TextLen_I, 1, Base_PS->TxtFile_PS ) ) {
  268. Base_PS->Errno_I = errno;
  269. return JAM_IO_ERROR;
  270. }
  271. }
  272. /*
  273. ** Add header
  274. */
  275. /* go to end of header file */
  276. if ( fseek( Base_PS->HdrFile_PS, 0, SEEK_END ) ) {
  277. Base_PS->Errno_I = errno;
  278. return JAM_IO_ERROR;
  279. }
  280. /* calculate the size of all Subfields */
  281. TotLen_I = 0;
  282. if ( SubPack_PS ) {
  283. s_JamSubfield* Subfield_PS;
  284. for ( Subfield_PS = JAM_GetSubfield( SubPack_PS ); Subfield_PS;
  285. Subfield_PS = JAM_GetSubfield( NULL ) )
  286. TotLen_I += sizeof( s_JamSaveSubfield ) + Subfield_PS->DatLen;
  287. }
  288. Header_PS->SubfieldLen = TotLen_I;
  289. /* go to end of index file */
  290. if ( fseek( Base_PS->IdxFile_PS, 0, SEEK_END ) ) {
  291. Base_PS->Errno_I = errno;
  292. return JAM_IO_ERROR;
  293. }
  294. /* find out new message number (for message header) */
  295. Offset_I = ftell( Base_PS->IdxFile_PS );
  296. if ( Offset_I == -1 ) {
  297. Base_PS->Errno_I = errno;
  298. return JAM_IO_ERROR;
  299. }
  300. /* update header */
  301. Header_PS->MsgNum = Offset_I / sizeof( s_JamIndex ) +
  302. BaseHeader_S.BaseMsgNum;
  303. memcpy( Header_PS->Signature, HEADERSIGNATURE, 4 );
  304. Header_PS->Revision = CURRENTREVLEV;
  305. /* go to end of header file */
  306. if ( fseek( Base_PS->HdrFile_PS, 0, SEEK_END ) ) {
  307. Base_PS->Errno_I = errno;
  308. return JAM_IO_ERROR;
  309. }
  310. /* find out new header offset (for index record) */
  311. Offset_I = ftell( Base_PS->HdrFile_PS );
  312. if ( Offset_I == -1 ) {
  313. Base_PS->Errno_I = errno;
  314. return JAM_IO_ERROR;
  315. }
  316. Index_S.HdrOffset = Offset_I;
  317. /* write new header */
  318. if ( 1 > fwritejammsgheader(Base_PS->HdrFile_PS,Header_PS) ) {
  319. Base_PS->Errno_I = errno;
  320. return JAM_IO_ERROR;
  321. }
  322. /* write Subfields */
  323. if ( SubPack_PS ) {
  324. s_JamSubfield* Subfield_PS;
  325. char User_AC[101];
  326. /* clear username */
  327. User_AC[0] = 0;
  328. for ( Subfield_PS = JAM_GetSubfield( SubPack_PS ); Subfield_PS;
  329. Subfield_PS = JAM_GetSubfield( NULL ) ) {
  330. /* first, save Subfield header */
  331. if ( 1 > fwritejamsavesubfield(Base_PS->HdrFile_PS,(s_JamSaveSubfield *)Subfield_PS) ) {
  332. Base_PS->Errno_I = errno;
  333. return JAM_IO_ERROR;
  334. }
  335. /* then, save Subfield data if any*/
  336. if(Subfield_PS->DatLen) {
  337. if ( 1 > fwrite( Subfield_PS->Buffer, Subfield_PS->DatLen,
  338. 1, Base_PS->HdrFile_PS ) ) {
  339. Base_PS->Errno_I = errno;
  340. return JAM_IO_ERROR;
  341. }
  342. }
  343. /* store username for index file */
  344. if ( Subfield_PS->LoID == JAMSFLD_RECVRNAME ) {
  345. memcpy( User_AC, Subfield_PS->Buffer, Subfield_PS->DatLen );
  346. User_AC[ Subfield_PS->DatLen ] = 0;
  347. }
  348. }
  349. /* update index record */
  350. if ( User_AC[0] )
  351. Index_S.UserCRC = JAM_Crc32( User_AC, strlen( User_AC ) );
  352. else
  353. Index_S.UserCRC = JAM_NO_CRC;
  354. }
  355. else
  356. /* update index record */
  357. Index_S.UserCRC = JAM_NO_CRC;
  358. /*
  359. ** Add index
  360. */
  361. /* write index record */
  362. if ( 1 > fwritejamindex(Base_PS->IdxFile_PS,&Index_S) ) {
  363. Base_PS->Errno_I = errno;
  364. return JAM_IO_ERROR;
  365. }
  366. if(!(Header_PS->Attribute & JAM_MSG_DELETED))
  367. BaseHeader_S.ActiveMsgs++; /* Only increase ActiveMsgs if JAM_MSG_DELETED not set */
  368. /* write message base header */
  369. Status_I = JAM_WriteMBHeader( Base_PS, &BaseHeader_S );
  370. if ( Status_I )
  371. return Status_I;
  372. return 0;
  373. }
  374. /***********************************************************************
  375. **
  376. ** JAM_AddEmptyMessage - Add a empty message entry to a message base
  377. **
  378. ***********************************************************************/
  379. int JAM_AddEmptyMessage( s_JamBase* Base_PS)
  380. {
  381. s_JamIndex Index_S;
  382. if ( !Base_PS )
  383. return JAM_BAD_PARAM;
  384. if ( !Base_PS->Locked_I )
  385. return JAM_NOT_LOCKED;
  386. /* go to end of index file */
  387. if ( fseek( Base_PS->IdxFile_PS, 0, SEEK_END ) ) {
  388. Base_PS->Errno_I = errno;
  389. return JAM_IO_ERROR;
  390. }
  391. /*
  392. ** Add index
  393. */
  394. Index_S.HdrOffset = 0xffffffff;
  395. Index_S.UserCRC = 0xffffffff;
  396. /* write index record */
  397. if ( 1 > fwritejamindex(Base_PS->IdxFile_PS,&Index_S) ) {
  398. Base_PS->Errno_I = errno;
  399. return JAM_IO_ERROR;
  400. }
  401. return 0;
  402. }
  403. /***********************************************************************
  404. **
  405. ** JAM_DeleteMessage - Delete message from messagebase
  406. **
  407. ***********************************************************************/
  408. int JAM_DeleteMessage( s_JamBase* Base_PS,
  409. uint32_t MsgNo_I )
  410. {
  411. s_JamBaseHeader BaseHeader_S;
  412. s_JamMsgHeader Header_S;
  413. s_JamIndex Index_S;
  414. int Status_I;
  415. uint32_t OldAttribute_I;
  416. if ( !Base_PS )
  417. return JAM_BAD_PARAM;
  418. if ( !Base_PS->Locked_I )
  419. return JAM_NOT_LOCKED;
  420. /* read message base header */
  421. Status_I = JAM_ReadMBHeader( Base_PS, &BaseHeader_S );
  422. if ( Status_I )
  423. return Status_I;
  424. /* find index record */
  425. if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ), SEEK_SET ) ) {
  426. Base_PS->Errno_I = errno;
  427. return JAM_IO_ERROR;
  428. }
  429. /* read index record */
  430. if ( 1 > freadjamindex( Base_PS->IdxFile_PS, &Index_S ) ) {
  431. Base_PS->Errno_I = errno;
  432. return JAM_IO_ERROR;
  433. }
  434. /* message is not there */
  435. if(Index_S.HdrOffset == 0xffffffff && Index_S.UserCRC == 0xffffffff)
  436. {
  437. return JAM_NO_MESSAGE;
  438. }
  439. /* find header */
  440. if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) {
  441. Base_PS->Errno_I = errno;
  442. return JAM_IO_ERROR;
  443. }
  444. /* read header */
  445. if ( 1 > freadjammsgheader( Base_PS->HdrFile_PS, &Header_S ) ) {
  446. Base_PS->Errno_I = errno;
  447. return JAM_IO_ERROR;
  448. }
  449. OldAttribute_I = Header_S.Attribute;
  450. Header_S.Attribute |= JAM_MSG_DELETED;
  451. /* find header */
  452. if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) {
  453. Base_PS->Errno_I = errno;
  454. return JAM_IO_ERROR;
  455. }
  456. /* write header */
  457. if ( 1 > fwritejammsgheader( Base_PS->HdrFile_PS, &Header_S ) ) {
  458. Base_PS->Errno_I = errno;
  459. return JAM_IO_ERROR;
  460. }
  461. /* find index record */
  462. if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ), SEEK_SET ) ) {
  463. Base_PS->Errno_I = errno;
  464. return JAM_IO_ERROR;
  465. }
  466. Index_S.HdrOffset = 0xffffffff;
  467. Index_S.UserCRC = 0xffffffff;
  468. /* write index record */
  469. if ( 1 > fwritejamindex(Base_PS->IdxFile_PS,&Index_S) ) {
  470. Base_PS->Errno_I = errno;
  471. return JAM_IO_ERROR;
  472. }
  473. if(!(OldAttribute_I & JAM_MSG_DELETED))
  474. BaseHeader_S.ActiveMsgs--; /* decrease ActiveMsgs if the message wasn't already deleted */
  475. /* write message base header */
  476. Status_I = JAM_WriteMBHeader( Base_PS, &BaseHeader_S );
  477. if ( Status_I )
  478. return Status_I;
  479. return 0;
  480. }
  481. /***********************************************************************
  482. **
  483. ** JAM_Errno - Report the latest C library error code
  484. **
  485. ***********************************************************************/
  486. int JAM_Errno( s_JamBase* Base_PS )
  487. {
  488. return Base_PS->Errno_I;
  489. }
  490. /***********************************************************************
  491. **
  492. ** JAM_ClearMsgHeader - Clear a message header
  493. **
  494. ***********************************************************************/
  495. int JAM_ClearMsgHeader( s_JamMsgHeader* Header_PS )
  496. {
  497. if (!Header_PS)
  498. return JAM_BAD_PARAM;
  499. memset( Header_PS, 0, sizeof( s_JamMsgHeader ) );
  500. memcpy( Header_PS->Signature, HEADERSIGNATURE, 4 );
  501. Header_PS->Revision = CURRENTREVLEV;
  502. Header_PS->MsgIdCRC = JAM_NO_CRC;
  503. Header_PS->ReplyCRC = JAM_NO_CRC;
  504. Header_PS->PasswordCRC = JAM_NO_CRC;
  505. return 0;
  506. }