Compare commits

..

107 Commits

Author SHA1 Message Date
hoa.nguyen%intel.com
22c40d96b2 removed the report of db filesize in GetStorageInUse.
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55763 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-08 21:54:27 +00:00
hoa.nguyen%intel.com
06a79b2069 fixed a bug in SetStoredContentLength so that it will update m_StorageInUse in nsNetDiskCache.
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55762 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-08 21:53:57 +00:00
hoa.nguyen%intel.com
ebc4face0d Added SetDiskCacheFolder for filecache test.
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55608 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-07 22:08:45 +00:00
hoa.nguyen%intel.com
150696bb86 Fixed DB corruption detection and error recovery logic. Removed Preference. Added routine for the special entry in DB.
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55606 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-07 22:07:56 +00:00
hoa.nguyen%intel.com
683045595b Added a few member according to the new nsIChannel i/f. Converted all the function to use raw file transport instead of nsIOService.
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55605 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-07 22:07:21 +00:00
hoa.nguyen%intel.com
7f09538b93 Fixed a memory leak on mInfo. Init() now also pass through recordID.
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55601 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-07 22:06:29 +00:00
hoa.nguyen%intel.com
bb364ef512 member name changed to follow the same convention. Added error recovery routine.
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55600 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-07 22:05:57 +00:00
hoa.nguyen%intel.com
7c96c92a19 sync now happens once every second. DB filesize is only updated upon sync. A special entry is added to record initial size and entry number of filecache.
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55597 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-07 22:04:56 +00:00
fur%netscape.com
a6defdef4c Merge portability changes and bug fixes from the trunk
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55586 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-07 17:40:40 +00:00
fur%netscape.com
76159a2caf Updated to NPL 1.1
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55504 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-07 01:40:45 +00:00
fur%netscape.com
1988cb05b5 Tweak comments
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55499 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-07 01:14:55 +00:00
fur%netscape.com
dd8c6b3bed Added nsINetDataCacheManager::SetDiskCacheFolder()
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55484 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-07 00:02:58 +00:00
fur%netscape.com
bc64749366 Account for arg changes in NewChannel() API
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55475 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-06 23:30:30 +00:00
fur%netscape.com
2e9287bd58 Match NewChannel() API changes on trunk
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55472 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-06 23:23:07 +00:00
fur%netscape.com
0f2274a140 Checkpoint
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55471 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-06 23:22:37 +00:00
fur%netscape.com
957fa10cac Retire nsINetDataCache::GetCapacity
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55469 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-06 23:16:10 +00:00
fur%netscape.com
e603146886 Track trunk API changes
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55467 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-06 23:15:32 +00:00
fur%netscape.com
cb698a0df1 + Retired nsINetDataCache::GetCapacity()
+ Fixed gcc build problem


git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55466 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-06 23:14:38 +00:00
fur%netscape.com
1b918d9ef0 + Added proxy channel arg to NewChannel()
+ Changed name of setProtocolPrivate/getProtocolPrivate to setAnnotation/getAnnotation\
+ Added inUse attribute
+ Touched up comments


git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55465 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-06 23:08:08 +00:00
fur%netscape.com
6407144c9f Removed capacity attribute
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55464 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-06 23:06:44 +00:00
fur%netscape.com
2ed563a178 Merge with trunk makefile.win
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@55462 18797224-902f-48f8-a5cc-f745e15eee43
1999-12-06 23:05:39 +00:00
fur%netscape.com
4becc0b508 Add assertion to cache manager to ensure that it is limiting cache occupancy
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@54566 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-29 15:23:34 +00:00
fur%netscape.com
7d5427ea31 Obey the MAX_CONTENT_LENGTH limit
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@54565 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-29 15:22:56 +00:00
fur%netscape.com
99904bcc48 Eliminate libs build target, as Warren has done for the rest of the tree
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@54545 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-29 02:15:04 +00:00
fur%netscape.com
bcb56c9593 Add strong ref to channel
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@54544 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-29 02:14:17 +00:00
fur%netscape.com
f18bc8e6cd Fix ownership issues. Change SetProtocolData/GetProtocolData args
to match new prototype.


git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@54109 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-21 07:51:56 +00:00
fur%netscape.com
7d14c5669a Handle NULL load group - they're supposed to be optional
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@54108 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-21 07:51:14 +00:00
fur%netscape.com
c0dd3df02e Fix tons of ref-counting ownership issues and other bug fixes
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@54107 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-21 07:50:25 +00:00
fur%netscape.com
e5cc84978f Checkpoint
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@54097 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-21 05:08:20 +00:00
fur%netscape.com
5694537330 Changed SetProtocolData/GetProtocolData to accept a tag argument so that
multiple cache clients can attach info to the cache database.


git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@54096 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-21 05:07:40 +00:00
fur%netscape.com
297c5ceba3 Add/modify APIs to track nsIChannel
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@54095 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-21 05:05:01 +00:00
fur%netscape.com
e0311312f7 Temporarily disable pref-reading code, since it doesn't work in the browser
and the code that measures the size of the cache db, since it's a performance
hog.


git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@54094 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-21 05:04:13 +00:00
fur%netscape.com
cf3dc77b02 Fix unitialized variable
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@54093 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-21 05:01:03 +00:00
fur%netscape.com
dd2506a737 Quash warnings
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53842 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-18 06:19:51 +00:00
fur%netscape.com
b1bee1f21c Merge with trunk
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53831 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-18 05:38:26 +00:00
fur%netscape.com
48ecc5625b Added review comments
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53674 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-16 19:46:28 +00:00
fur%netscape.com
1b791685e6 No longer need factory code. Its been moved to netwerk/cache/builds/nsNetDataCacheModule.cpp
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53663 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-16 18:21:11 +00:00
fur%netscape.com
dc94d1d6e2 Added review comments
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53647 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-16 10:08:26 +00:00
hoa.nguyen%intel.com
f5b437ade3 added Unix support
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53574 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-16 00:21:05 +00:00
hoa.nguyen%intel.com
8c0b4b3e4a changed NPL to MPL
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53573 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-16 00:16:33 +00:00
hoa.nguyen%intel.com
fb640ab144 added Truncate function
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53572 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-16 00:07:27 +00:00
hoa.nguyen%intel.com
106e263b33 added support for memory cache
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53570 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-16 00:00:54 +00:00
fur%netscape.com
85045a8552 Add TestCacheMgr
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53537 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-15 21:13:19 +00:00
fur%netscape.com
a2279be132 *** empty log message ***
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53536 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-15 21:12:58 +00:00
fur%netscape.com
0ce702d402 Don't call NS_ERROR() when a record ID is not found
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53533 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-15 21:12:17 +00:00
fur%netscape.com
f14d03cd67 Fixed CommitFlags()
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53531 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-15 21:11:14 +00:00
fur%netscape.com
b91343fdf6 Checkpoint
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53520 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-15 18:30:44 +00:00
fur%netscape.com
2c517489b5 Disable warning, so cache code can run
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53519 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-15 17:39:35 +00:00
(no author)
ae57da58eb This commit was manufactured by cvs2svn to create branch
'CacheIntegration_BRANCH'.

git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53517 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-15 17:10:07 +00:00
fur%netscape.com
8d4586dd65 Update components table and macro instantiations to conform to new definitions
in nsIGenericFactory.h


git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53499 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-15 09:06:41 +00:00
fur%netscape.com
9b473ad9be Added starting offset param to interceptAsyncRead() method
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53498 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-15 08:53:15 +00:00
fur%netscape.com
2ad227a994 Merged with trunk
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53496 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-15 08:01:58 +00:00
fur%netscape.com
94d8da33c1 Replace 1.0 NPL with 1.1 version
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53487 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-15 06:13:13 +00:00
fur%netscape.com
81c05809fd Remove dead files
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53486 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-15 06:08:40 +00:00
fur%netscape.com
e30547b2b2 Remove dead files
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53485 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-15 05:52:29 +00:00
fur%netscape.com
257f9cfaaa Fix Boogs. Replace 1.0 NPL with 1.1 version
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53484 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-15 05:51:02 +00:00
fur%netscape.com
96e2654e43 Replace 1.0 NPL with 1.1 NPL
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53474 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-14 20:35:26 +00:00
fur%netscape.com
3b023433be Replace 1.0 NPL with 1.1 version
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53472 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-14 19:56:44 +00:00
fur%netscape.com
1b89716afe Added more comments
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53471 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-14 19:50:30 +00:00
fur%netscape.com
ad02058877 Add comments. Change method names
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53470 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-14 18:51:57 +00:00
fur%netscape.com
fa8a3196e7 Merge with trunk
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53434 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-13 19:35:49 +00:00
fur%netscape.com
5c2c543e58 Fixed bugs which prevented embedded NUL characters
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53431 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-13 18:45:28 +00:00
fur%netscape.com
c588721cc0 Added NS_NewStorageStream().
Changed method name, Initialize ==> Init


git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53430 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-13 18:43:20 +00:00
fur%netscape.com
0b049b17ba Fix Boogs
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53429 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-13 18:41:01 +00:00
fur%netscape.com
854ef4631d Merge from trunk
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53268 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-11 22:29:20 +00:00
fur%netscape.com
051c558653 Detect failure to truncate cache entry
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53214 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-11 18:16:24 +00:00
fur%netscape.com
37a04adb09 Killed build warnings. Added stubs for unimplemented methods
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53072 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-10 06:05:33 +00:00
fur%netscape.com
c823c04b45 Combine cache components into module
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@53014 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-09 22:08:49 +00:00
fur%netscape.com
03cbd000eb Sync with trunk
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52998 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-09 17:36:48 +00:00
fur%netscape.com
a91e91a1c7 Added Windows makefiles so that the cache manager, file cache and
memory cache components are built as part of netlib and combined into
a single XPCOM module, named "nkcache.dll"


git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52970 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:44:04 +00:00
fur%netscape.com
be7a5a48b6 Added call to LimitCacheSize
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52968 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:40:41 +00:00
fur%netscape.com
b2bc7468e8 Add cache manager CID
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52967 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:38:20 +00:00
fur%netscape.com
9692dfd994 Add cache manager ProgID
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52966 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:37:30 +00:00
fur%netscape.com
f3edd4cfb5 Added an owning reference from nsDiskCacheRecordChannel to
its associated nsDiskCacheRecord.  Without this, the channel
may access free'ed memory.


git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52962 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:28:39 +00:00
fur%netscape.com
33403345c1 Rename class to avoid name collision with similar code in file cache.
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52961 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:25:28 +00:00
fur%netscape.com
20c850de23 Merge with tip
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52960 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:23:35 +00:00
fur%netscape.com
e8b619cd02 Merge with tip
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52959 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:18:25 +00:00
fur%netscape.com
eed396bb92 Stabilize ref-count during construction
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52946 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 18:46:17 +00:00
fur%netscape.com
41d44c070b Eliminate dead files
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52932 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-07 20:19:55 +00:00
fur%netscape.com
698ba42268 Revamped directory structure
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52922 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-06 19:36:16 +00:00
(no author)
1a0fd23991 This commit was manufactured by cvs2svn to create branch
'CacheIntegration_BRANCH'.

git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52912 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-06 03:43:56 +00:00
fur%netscape.com
67dded330b Add nsDiskCacheRecordChannel.cpp
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52876 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 22:18:26 +00:00
fur%netscape.com
936ff4777a Fix compilation errors on Win32
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52874 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 22:18:04 +00:00
fur%netscape.com
96c55e42f7 Accommodate API changes in nsINetDataCache
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52873 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 22:17:42 +00:00
fur%netscape.com
82fa0cf06a Got rid of GetReadOnly(). Added GetFlags()
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52872 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 22:15:05 +00:00
fur%netscape.com
98c8285334 First shot at Win32 makefile
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52869 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 22:03:02 +00:00
fur%netscape.com
bad4b683f4 Removed SetCapacity() method
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52868 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 22:01:26 +00:00
fur%netscape.com
cb5269a28a Checkpoint
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52864 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 21:47:25 +00:00
fur%netscape.com
74712f3635 Added binary I/O streams
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52860 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 20:02:06 +00:00
fur%netscape.com
9f8ea739db Correct error comment
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52859 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 20:01:39 +00:00
hoa.nguyen%intel.com
97a10dd7c6 Add offset writing for nsOutputStream
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52789 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 18:02:39 +00:00
hoa.nguyen%intel.com
85a132fac0 Add command line switch to test memory and disk cache.
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52788 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 18:01:28 +00:00
hoa.nguyen%intel.com
e594eee877 Add proxy channel interface, and misc bug fixes.
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@52787 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 17:59:42 +00:00
hoa.nguyen%intel.com
9148eee3d6 Initial checkin of disk cache modules
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@51580 18797224-902f-48f8-a5cc-f745e15eee43
1999-10-22 22:37:18 +00:00
hoa.nguyen%intel.com
b5989a8382 Initial checkin of disk cache module
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@51579 18797224-902f-48f8-a5cc-f745e15eee43
1999-10-22 22:36:07 +00:00
fur%netscape.com
2b861f60d9 Create a new channel for every call to Write()
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@51335 18797224-902f-48f8-a5cc-f745e15eee43
1999-10-21 01:35:51 +00:00
fur%netscape.com
87db050b37 Added tests for:
nsINetDataCache::GetStorageInUse()
    nsINetDataCacheRecord::SetContentLength()
    nsIOutputStream::Write(), using non-zero starting offsets


git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@51071 18797224-902f-48f8-a5cc-f745e15eee43
1999-10-18 23:55:44 +00:00
fur%netscape.com
ffe483cf95 Initial cut at memory-cache functionality is complete
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@51067 18797224-902f-48f8-a5cc-f745e15eee43
1999-10-18 23:46:08 +00:00
fur%netscape.com
52aa17a1c3 Incorporate nsStorageStream into xpcom.dll
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@50814 18797224-902f-48f8-a5cc-f745e15eee43
1999-10-15 07:40:42 +00:00
fur%netscape.com
5fdb3aa69e Initial implementation of 'storage stream' - used as the heart of the memory cache
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@50812 18797224-902f-48f8-a5cc-f745e15eee43
1999-10-15 07:39:45 +00:00
fur%netscape.com
8cae473bc0 Add opaque keys to nsHashtable
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@50811 18797224-902f-48f8-a5cc-f745e15eee43
1999-10-15 07:38:01 +00:00
fur%netscape.com
0719303755 Fix linkage problem
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@50810 18797224-902f-48f8-a5cc-f745e15eee43
1999-10-15 07:37:21 +00:00
fur%netscape.com
90d3e40858 Fix bugs in Next(). Prev() and IsDone()
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@50809 18797224-902f-48f8-a5cc-f745e15eee43
1999-10-15 07:36:35 +00:00
fur%netscape.com
c792b2d35c Changed IDL to generate identical C++ headers, but with better scriptability
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@50808 18797224-902f-48f8-a5cc-f745e15eee43
1999-10-15 07:32:04 +00:00
fur%netscape.com
7a4377d840 Initial cut at memory cache
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@50806 18797224-902f-48f8-a5cc-f745e15eee43
1999-10-15 07:24:06 +00:00
fur%netscape.com
a5fa416010 Added TestRawCache.cpp
git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@50804 18797224-902f-48f8-a5cc-f745e15eee43
1999-10-15 07:19:52 +00:00
(no author)
49d00db5e2 This commit was manufactured by cvs2svn to create branch
'CacheIntegration_BRANCH'.

git-svn-id: svn://10.0.0.236/branches/CacheIntegration_BRANCH@50589 18797224-902f-48f8-a5cc-f745e15eee43
1999-10-13 10:24:13 +00:00
189 changed files with 24580 additions and 92340 deletions

File diff suppressed because it is too large Load Diff

38
mozilla/netwerk/cache/Makefile.in vendored Normal file
View File

@@ -0,0 +1,38 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = \
public \
memcache \
filecache \
mgr \
build \
$(NULL)
include $(topsrcdir)/config/rules.mk

33
mozilla/netwerk/cache/Makefile.win vendored Executable file
View File

@@ -0,0 +1,33 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..
DIRS= \
public \
mgr \
memcache \
filecache \
build \
$(NULL)
include <$(DEPTH)\config\rules.mak>

54
mozilla/netwerk/cache/build/Makefile.in vendored Normal file
View File

@@ -0,0 +1,54 @@
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = nkcacke
LIBRARY_NAME = necko_cache
IS_COMPONENT = 1
CPPSRCS = nsNetDataCacheModule.cpp
SHARED_LIBRARY_LIBS = \
$(DIST)/lib/libnkcachemgr_s.a \
$(DIST)/lib/libnkfilecache_s.a \
$(DIST)/lib/libnkmemcache_s.a \
$(DIST)/lib/libmozdbm_s.a \
$(DIST)/lib/libxpcomio_s.a \
$(NULL)
LOCAL_INCLUDES = \
-I$(DEPTH)/netwerk/cache/memcache \
-I$(DEPTH)/netwerk/cache/filecache \
-I$(DEPTH)/netwerk/cache/mgr \
$(NULL)
EXTRA_DSO_LDOPTS = \
$(MKSHLIB_FORCE_ALL) \
$(SHARED_LIBRARY_LIBS) \
$(MKSHLIB_UNFORCE_ALL) \
$(NULL)
include $(topsrcdir)/config/rules.mk
$(LIBRARY) $(SHARED_LIBRARY): $(SHARED_LIBRARY_LIBS) Makefile

View File

@@ -0,0 +1,51 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
DEPTH=..\..\..
MODULE=nkcache
MAKE_OBJ_TYPE=DLL
DLLNAME=nkcache
DLL=.\$(OBJDIR)\$(DLLNAME).dll
CPP_OBJS= \
.\$(OBJDIR)\nsNetDataCacheModule.obj \
$(NULL)
LLIBS= \
$(DIST)\lib\nkcachemgr_s.lib \
$(DIST)\lib\nkfilecache_s.lib \
$(DIST)\lib\nkmemcache_s.lib \
$(DIST)\lib\dbm32.lib \
$(DIST)\lib\xpcom.lib \
$(LIBNSPR)
INCS = $(INCS) \
-I$(DEPTH)\netwerk\cache\memcache \
-I$(DEPTH)\netwerk\cache\filecache \
-I$(DEPTH)\netwerk\cache\mgr \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib

View File

@@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
#include "nsCOMPtr.h"
#include "nsIModule.h"
#include "nscore.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIGenericFactory.h"
#include "nsINetDataCache.h"
#include "nsINetDataCacheManager.h"
#include "nsMemCacheCID.h"
#include "nsMemCache.h"
#include "nsNetDiskCache.h"
#include "nsNetDiskCacheCID.h"
#include "nsCacheManager.h"
// Factory method to create a new nsMemCache instance. Used
// by nsNetDataCacheModule
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMemCache, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNetDiskCache, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsCacheManager, Init)
static nsModuleComponentInfo components[] = {
{ "Memory Cache", NS_MEM_CACHE_FACTORY_CID, NS_NETWORK_MEMORY_CACHE_PROGID, nsMemCacheConstructor },
{ "File Cache", NS_NETDISKCACHE_CID, NS_NETWORK_FILE_CACHE_PROGID, nsNetDiskCacheConstructor },
{ "Cache Manager",NS_CACHE_MANAGER_CID, NS_NETWORK_CACHE_MANAGER_PROGID,nsCacheManagerConstructor }
};
NS_IMPL_NSGETMODULE("Network Data Cache", components)

View File

@@ -0,0 +1,60 @@
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is Mozilla Communicator.
#
# The Initial Developer of the Original Code is Intel Corp.
# Portions created by Intel Corp. are
# Copyright (C) 1999, 1999 Intel Corp. All
# Rights Reserved.
#
# Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
# Carl Wong <carl.wong@intel.com>
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
VPATH = @srcdir@
srcdir = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = nkcache
LIBRARY_NAME = nkfilecache_s
REQUIRES = nspr dbm
EXTRA_DSO_LDOPTS += -L$(DIST)/lib -lmozdbm_s
EXPORTS=nsNetDiskCacheCID.h \
nsNetDiskCache.h \
nsIDBAccessor.h \
nsDBAccessor.h \
$(NULL)
CPPSRCS = \
nsDBAccessor.cpp\
nsDBEnumerator.cpp \
nsNetDiskCache.cpp \
nsDiskCacheRecord.cpp \
nsDiskCacheRecordChannel.cpp \
$(NULL)
EXTRA_LIBS = $(NSPR_LIBS)
# we don't want the shared lib, but we want to force the creation of a
# static lib.
override NO_SHARED_LIB=1
override NO_STATIC_LIB=
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,44 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = nkcache
LIBRARY_NAME = nkfilecache_s
CPP_OBJS= \
.\$(OBJDIR)\nsDBAccessor.obj \
.\$(OBJDIR)\nsDBEnumerator.obj \
.\$(OBJDIR)\nsNetDiskCache.obj \
.\$(OBJDIR)\nsDiskCacheRecord.obj \
.\$(OBJDIR)\nsDiskCacheRecordChannel.obj \
$(NULL)
EXPORTS=nsNetDiskCacheCID.h
include <$(DEPTH)\config\rules.mak>
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -rf $(OBJDIR)
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,416 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
/*
* This file is part of filecache implementation.
*
* nsIDBAccessor is a interface that shields all the direct database access
* method from nsNetDiskCache.
*
* nsDBAccessor is a implementation of the nsIDBAccessor interface. It
* uses dbm(Berkely) as the database.
*
* a nsDiskCacheRecord is mapped into two entries in the database,
* key->recordID
* recordID->metadata
*/
#include "nsDBAccessor.h"
#include "nscore.h"
#include "prtypes.h"
#include "plhash.h"
#include "nsCRT.h"
nsDBAccessor::nsDBAccessor() :
mDB(0) ,
mDBFile(0) ,
mSessionID(0) ,
mSessionCntr(0) ,
mDBFilesize(0)
{
mLastSyncTime = PR_IntervalNow() ;
NS_INIT_REFCNT();
}
nsDBAccessor::~nsDBAccessor()
{
Shutdown() ;
}
//
// Implement nsISupports methods
//
NS_IMPL_ISUPPORTS(nsDBAccessor, NS_GET_IID(nsIDBAccessor))
///////////////////////////////////////////////////////////
// nsIDBAccessor methods
NS_IMETHODIMP
nsDBAccessor::Init(nsIFileSpec* dbfile)
{
char* dbname ;
// this should cover all platforms.
dbfile->GetNativePath(&dbname) ;
mDBFile = dbfile ;
// FUR - how is page size chosen ? It's worth putting a comment
// in here about the possible usefulness of tuning these parameters
HASHINFO hash_info = {
16*1024 , /* bucket size */
0 , /* fill factor */
0 , /* number of elements */
0 , /* bytes to cache */
0 , /* hash function */
0} ; /* byte order */
mDB = dbopen(dbname,
O_RDWR | O_CREAT ,
0600 ,
DB_HASH ,
& hash_info) ;
nsCRT::free(dbname) ;
if(!mDB)
return NS_ERROR_FAILURE ;
// set mSessionID
DBT db_key, db_data ;
db_key.data = NS_CONST_CAST(char*, SessionKey) ;
db_key.size = PL_strlen(SessionKey) ;
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
if(status == -1) {
NS_ERROR("ERROR: failed get session id in database.") ;
return NS_ERROR_FAILURE ;
}
if(status == 0) {
// get the last session id
PRInt16 *old_ID = NS_STATIC_CAST(PRInt16*, db_data.data) ;
if(*old_ID < ini_sessionID) {
NS_ERROR("ERROR: Bad Session ID in database, corrupted db.") ;
return NS_ERROR_FAILURE ;
}
mSessionID = *old_ID + 1 ;
}
else if(status == 1) {
// must be a new db
mSessionID = ini_sessionID ;
}
db_data.data = NS_REINTERPRET_CAST(void*, &mSessionID) ;
db_data.size = sizeof(PRInt16) ;
// store the new session id
status = (*mDB->put)(mDB, &db_key, &db_data, 0) ;
if(status == 0) {
(*mDB->sync)(mDB, 0) ;
// initialize database filesize
return mDBFile->GetFileSize(&mDBFilesize) ;
}
else {
NS_ERROR("reset session ID failure.") ;
return NS_ERROR_FAILURE ;
}
}
NS_IMETHODIMP
nsDBAccessor::Shutdown(void)
{
if(mDB) {
(*mDB->sync)(mDB, 0) ;
(*mDB->close)(mDB) ;
mDB = nsnull ;
}
return NS_OK ;
}
NS_IMETHODIMP
nsDBAccessor::Get(PRInt32 aID, void** anEntry, PRUint32 *aLength)
{
if(!anEntry)
return NS_ERROR_NULL_POINTER ;
*anEntry = nsnull ;
*aLength = 0 ;
NS_ASSERTION(mDB, "no database") ;
DBT db_key, db_data ;
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
db_key.size = sizeof(PRInt32) ;
int status = 0 ;
status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
if(status == 0) {
*anEntry = db_data.data ;
*aLength = db_data.size ;
return NS_OK ;
}
else if(status == 1)
return NS_OK ;
else
return NS_ERROR_FAILURE ;
}
NS_IMETHODIMP
nsDBAccessor::Put(PRInt32 aID, void* anEntry, PRUint32 aLength)
{
NS_ASSERTION(mDB, "no database") ;
DBT db_key, db_data ;
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
db_key.size = sizeof(PRInt32) ;
db_data.data = anEntry ;
db_data.size = aLength ;
if(0 == (*mDB->put)(mDB, &db_key, &db_data, 0)) {
return Sync() ;
}
else {
return NS_ERROR_FAILURE ;
}
}
/*
* It's more important to remove the id->metadata entry first since
* key->id mapping is just a reference
*/
NS_IMETHODIMP
nsDBAccessor::Del(PRInt32 aID, void* anEntry, PRUint32 aLength)
{
NS_ASSERTION(mDB, "no database") ;
DBT db_key ;
// delete recordID->metadata
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
db_key.size = sizeof(PRInt32) ;
PRInt32 status = -1 ;
status = (*mDB->del)(mDB, &db_key, 0) ;
if(-1 == status) {
return NS_ERROR_FAILURE ;
}
// delete key->recordID
db_key.data = anEntry ;
db_key.size = aLength ;
status = (*mDB->del)(mDB, &db_key, 0) ;
if(-1 == status) {
return NS_ERROR_FAILURE ;
}
return Sync() ;
}
NS_IMETHODIMP
nsDBAccessor::GetID(const char* key, PRUint32 length, PRInt32* aID)
{
NS_ASSERTION(mDB, "no database") ;
DBT db_key, db_data ;
db_key.data = NS_CONST_CAST(char*, key) ;
db_key.size = length ;
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
if(status == 0) {
// found recordID
*aID = *(NS_REINTERPRET_CAST(PRInt32*, db_data.data)) ;
return NS_OK ;
}
else if(status == 1) {
// create a new one
PRInt32 id = 0 ;
id = mSessionID << 16 | mSessionCntr++ ;
// add new id into mDB
db_data.data = NS_REINTERPRET_CAST(void*, &id) ;
db_data.size = sizeof(PRInt32) ;
status = (*mDB->put)(mDB, &db_key, &db_data, 0) ;
if(status != 0) {
NS_ERROR("updating db failure.") ;
return NS_ERROR_FAILURE ;
}
*aID = id ;
return Sync() ;
}
else {
NS_ERROR("ERROR: keydb failure.") ;
return NS_ERROR_FAILURE ;
}
}
NS_IMETHODIMP
nsDBAccessor::EnumEntry(void** anEntry, PRUint32* aLength, PRBool bReset)
{
if(!anEntry)
return NS_ERROR_NULL_POINTER ;
*anEntry = nsnull ;
*aLength = 0 ;
NS_ASSERTION(mDB, "no database") ;
PRUint32 flag ;
if(bReset)
flag = R_FIRST ;
else
flag = R_NEXT ;
DBT db_key, db_data ;
PRUint32 len = PL_strlen(SessionKey) ;
int status ;
do {
status = (*mDB->seq)(mDB, &db_key, &db_data, flag) ;
flag = R_NEXT ;
if(status == -1)
return NS_ERROR_FAILURE ;
// get next if it's a key->recordID
if(db_key.size > sizeof(PRInt32) && db_data.size == sizeof(PRInt32))
continue ;
// get next if it's a sessionID entry
if(db_key.size == len && db_data.size == sizeof(PRInt16))
continue ;
// recordID is always 32 bits long
if(db_key.size == sizeof(PRInt32))
break ;
} while(!status) ;
if (0 == status) {
*anEntry = db_data.data ;
*aLength = db_data.size ;
}
return NS_OK ;
}
/*
* returns the cached database file size.
* mDBFilesize will be updated during Sync().
*/
NS_IMETHODIMP
nsDBAccessor::GetDBFilesize(PRUint32* aSize)
{
*aSize = mDBFilesize ;
return NS_OK ;
}
NS_IMETHODIMP
nsDBAccessor::GetSpecialEntry(void** anEntry, PRUint32* aLength)
{
if(!anEntry)
return NS_ERROR_NULL_POINTER ;
*anEntry = nsnull ;
*aLength = 0 ;
DBT db_key, db_data ;
db_key.data = NS_CONST_CAST(char*, SpecialEntry) ;
db_key.size = PL_strlen(SpecialEntry) ;
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
if(status == -1) {
NS_ERROR("ERROR: failed get special entry in database.") ;
return NS_ERROR_FAILURE ;
}
if(status == 0) {
*anEntry = db_data.data ;
*aLength = db_data.size ;
}
return NS_OK ;
}
NS_IMETHODIMP
nsDBAccessor::SetSpecialEntry(void* anEntry, PRUint32 aLength)
{
DBT db_key, db_data ;
db_key.data = NS_CONST_CAST(char*, SpecialEntry) ;
db_key.size = PL_strlen(SpecialEntry) ;
db_data.data = anEntry ;
db_data.size = aLength ;
if(0 == (*mDB->put)(mDB, &db_key, &db_data, 0)) {
(*mDB->sync)(mDB, 0) ;
return NS_OK ;
}
else {
return NS_ERROR_FAILURE ;
}
}
/*
* sync routine is only called when the SyncInterval is reached. Otherwise
* it just returns. If db synced, the filesize will be updated at the
* same time.
*/
nsresult
nsDBAccessor::Sync(void)
{
PRIntervalTime time = PR_IntervalNow() ;
PRIntervalTime duration = time - mLastSyncTime ;
if (PR_IntervalToMilliseconds(duration) > SyncInterval) {
int status = (*mDB->sync)(mDB, 0) ;
if(status == 0) {
// printf("\tsynced\n") ;
mLastSyncTime = time ;
// update db filesize here
return mDBFile->GetFileSize(&mDBFilesize) ;
} else
return NS_ERROR_FAILURE ;
} else {
// printf("\tnot synced\n") ;
return NS_OK ;
}
}

View File

@@ -0,0 +1,93 @@
/*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
/*
* This file is part of filecache implementation.
*
* nsIDBAccessor is a interface that shields all the direct database access
* method from nsNetDiskCache.
*
* nsDBAccessor is a implementation of the nsIDBAccessor interface. It
* uses dbm(Berkely) as the database.
*
*/
#ifndef _NSIDBACCESSOR_H_
#define _NSIDBACCESSOR_H_
#include "nsIDBAccessor.h"
#include "mcom_db.h"
#include "prinrval.h"
#include "nsCOMPtr.h"
// bogus string for the key of session id
static const char * const SessionKey = "SK" ;
// bogus string for the size
static const char * const SpecialEntry = "SE" ;
// initial session id number
static const PRInt16 ini_sessionID = 0xff ;
static const PRUint16 SyncInterval = 1000 ;
class nsDBAccessor : public nsIDBAccessor
{
public:
NS_DECL_ISUPPORTS
nsDBAccessor() ;
virtual ~nsDBAccessor() ;
NS_IMETHOD Init(nsIFileSpec* dbfile) ;
NS_IMETHOD Shutdown(void) ;
NS_IMETHOD Put(PRInt32 aID, void* anEntry, PRUint32 aLength) ;
NS_IMETHOD Get(PRInt32 aID, void** anEntry, PRUint32 *aLength) ;
NS_IMETHOD Del(PRInt32 aID, void* anEntry, PRUint32 aLength) ;
NS_IMETHOD GetID(const char* key, PRUint32 length, PRInt32* aID) ;
NS_IMETHOD EnumEntry(void* *anEntry, PRUint32* aLength, PRBool bReset) ;
NS_IMETHOD GetDBFilesize(PRUint32* aSize) ;
NS_IMETHOD GetSpecialEntry(void** anEntry, PRUint32 *aLength) ;
NS_IMETHOD SetSpecialEntry(void* anEntry, PRUint32 aLength) ;
protected:
nsresult Sync(void) ;
private:
DB * mDB ;
nsCOMPtr<nsIFileSpec> mDBFile ;
PRInt16 mSessionID ;
PRInt16 mSessionCntr ;
PRIntervalTime mLastSyncTime ;
PRUint32 mDBFilesize ; // cached DB filesize,
// updated on every sync for now
} ;
#endif // _NSIDBACCESSOR_H_

View File

@@ -0,0 +1,108 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
/*
* This file is part of filecache implementation.
*
* It implements a simple iterator for the database, see nsDBAccessor.
*/
#include "nsDBEnumerator.h"
#include "nsDiskCacheRecord.h"
nsDBEnumerator::nsDBEnumerator(nsIDBAccessor* aDB, nsNetDiskCache* aCache) :
m_DB(aDB) ,
m_DiskCache(aCache) ,
m_tempEntry(0) ,
m_tempEntry_length(0) ,
m_CacheEntry(0) ,
m_bReset(PR_TRUE)
{
NS_INIT_REFCNT();
}
nsDBEnumerator::~nsDBEnumerator()
{
NS_IF_RELEASE(m_CacheEntry) ;
}
//
// Implement nsISupports methods
//
NS_IMPL_ISUPPORTS(nsDBEnumerator, NS_GET_IID(nsIEnumerator))
/////////////////////////////////////////////////////////////////
// nsISimpleEnumerator methods
NS_IMETHODIMP
nsDBEnumerator::HasMoreElements(PRBool *_retval)
{
*_retval = PR_FALSE ;
nsresult rv = m_DB->EnumEntry(&m_tempEntry, &m_tempEntry_length, m_bReset) ;
if(NS_FAILED(rv)) {
// do some error recovery
m_DiskCache->DBRecovery() ;
return rv ;
}
m_bReset = PR_FALSE ;
if(m_tempEntry && m_tempEntry_length != 0)
*_retval = PR_TRUE ;
return NS_OK ;
}
// this routine does not create a new item by itself
// Rather it reuses the item inside the object. So if you need to use the
// item later, you have to
// create a new item specifically, using copy constructor or some other dup
// function. And don't forget to release it after you're done
//
NS_IMETHODIMP
nsDBEnumerator::GetNext(nsISupports **_retval)
{
if(!m_CacheEntry) {
m_CacheEntry = new nsDiskCacheRecord(m_DB, m_DiskCache) ;
if(m_CacheEntry)
NS_ADDREF(m_CacheEntry) ;
else
return NS_ERROR_OUT_OF_MEMORY ;
}
if(!_retval)
return NS_ERROR_NULL_POINTER ;
*_retval = nsnull ;
nsresult rv = m_CacheEntry->RetrieveInfo(m_tempEntry, m_tempEntry_length) ;
if(NS_FAILED(rv))
return rv ;
*_retval = NS_STATIC_CAST(nsISupports*, m_CacheEntry) ;
NS_ADDREF(*_retval) ; // all good getter addref
return NS_OK ;
}

View File

@@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
/*
* This file is part of filecache implementation.
*
* It implements a simple iterator for the database, see nsDBAccessor.
*/
#ifndef _NS_DBENUMERATOR_H_
#define _NS_DBENUMERATOR_H_
#include "nsISimpleEnumerator.h"
#include "nsINetDataCacheRecord.h"
#include "nsIDBAccessor.h"
#include "nsCOMPtr.h"
#include "nsNetDiskCache.h"
#include "nsDiskCacheRecord.h"
class nsCachedDiskData ; /* forward decl */
class nsDBEnumerator : public nsISimpleEnumerator {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
nsDBEnumerator(nsIDBAccessor* aDB, nsNetDiskCache* aCache) ;
virtual ~nsDBEnumerator() ;
private:
nsCOMPtr<nsIDBAccessor> m_DB ;
nsCOMPtr<nsNetDiskCache> m_DiskCache ;
void * m_tempEntry ;
PRUint32 m_tempEntry_length ;
nsDiskCacheRecord* m_CacheEntry ;
PRBool m_bReset ;
};
#endif // _NS_DBENUMERATOR_H_

View File

@@ -0,0 +1,456 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#include "nsDiskCacheRecord.h"
#include "nsINetDataDiskCache.h"
#include "nsNetDiskCacheCID.h"
#include "nsDiskCacheRecordChannel.h"
#include "nsFileStream.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIProtocolHandler.h"
#include "nsIIOService.h"
#include "nsIAllocator.h"
#include "plstr.h"
#include "prprf.h"
#include "prmem.h"
#include "prlog.h"
#include "prtypes.h"
#include "netCore.h"
#include "nsDBAccessor.h"
#if !defined(IS_LITTLE_ENDIAN) && !defined(IS_BIG_ENDIAN)
ERROR! Must have a byte order
#endif
#ifdef IS_LITTLE_ENDIAN
#define COPY_INT32(_a,_b) memcpy(_a, _b, sizeof(int32))
#else
#define COPY_INT32(_a,_b) /* swap */ \
do { \
((char *)(_a))[0] = ((char *)(_b))[3]; \
((char *)(_a))[1] = ((char *)(_b))[2]; \
((char *)(_a))[2] = ((char *)(_b))[1]; \
((char *)(_a))[3] = ((char *)(_b))[0]; \
} while(0)
#endif
nsDiskCacheRecord::nsDiskCacheRecord(nsIDBAccessor* db, nsNetDiskCache* aCache) :
mKey(0) ,
mKeyLength(0) ,
mRecordID(0) ,
mMetaData(0) ,
mMetaDataLength(0) ,
mDB(db) ,
mInfo(0) ,
mInfoSize(0) ,
mNumChannels(0) ,
mDiskCache(aCache)
{
NS_INIT_REFCNT();
NS_ASSERTION(mDiskCache, "Must have an nsNetDiskCache");
NS_ADDREF(mDiskCache);
}
// mem alloced. so caller should do free() on key.
NS_IMETHODIMP
nsDiskCacheRecord::Init(const char* key, PRUint32 length, PRInt32 ID)
{
NS_NewFileSpec(getter_AddRefs(mFile));
if(!mFile)
return NS_ERROR_OUT_OF_MEMORY ;
// copy key
mKeyLength = length ;
mKey = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
if(!mKey)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(mKey, key, length) ;
// get RecordID
mRecordID = ID ;
// setup the file name
nsCOMPtr<nsIFileSpec> dbFolder ;
mDiskCache->GetDiskCacheFolder(getter_AddRefs(dbFolder)) ;
nsresult rv = mFile->FromFileSpec(dbFolder) ;
if(NS_FAILED(rv))
return NS_ERROR_FAILURE ;
// dir is a hash result of mRecordID%32, hope it's enough
char filename[9], dirName[3] ;
PR_snprintf(dirName, 3, "%02x", (((PRUint32)mRecordID) % 32)) ;
mFile->AppendRelativeUnixPath(dirName) ;
PR_snprintf(filename, 9, "%08x", mRecordID) ;
mFile->AppendRelativeUnixPath(filename) ;
return NS_OK ;
}
nsDiskCacheRecord::~nsDiskCacheRecord()
{
if(mKey)
nsAllocator::Free(mKey) ;
if(mMetaData)
nsAllocator::Free(mMetaData) ;
if(mInfo)
nsAllocator::Free(mInfo) ;
NS_IF_RELEASE(mDiskCache);
}
//
// Implement nsISupports methods
//
NS_IMPL_ISUPPORTS(nsDiskCacheRecord, NS_GET_IID(nsINetDataCacheRecord))
///////////////////////////////////////////////////////////////////////
// nsINetDataCacheRecord methods
// yes, mem alloced on *_retval.
NS_IMETHODIMP
nsDiskCacheRecord::GetKey(PRUint32 *length, char** _retval)
{
if(!_retval)
return NS_ERROR_NULL_POINTER ;
*length = mKeyLength ;
*_retval = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
if(!*_retval)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(*_retval, mKey, mKeyLength) ;
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecord::GetRecordID(PRInt32* aRecordID)
{
*aRecordID = mRecordID ;
return NS_OK ;
}
// yes, mem alloced on *_retval.
NS_IMETHODIMP
nsDiskCacheRecord::GetMetaData(PRUint32 *length, char **_retval)
{
if(!_retval)
return NS_ERROR_NULL_POINTER ;
// always null the return value first.
*_retval = nsnull ;
*length = mMetaDataLength ;
if(mMetaDataLength) {
*_retval = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
if(!*_retval)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(*_retval, mMetaData, mMetaDataLength) ;
}
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecord::SetMetaData(PRUint32 length, const char* data)
{
// set the mMetaData
mMetaDataLength = length ;
if(mMetaData)
nsAllocator::Free(mMetaData) ;
mMetaData = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
if(!mMetaData) {
return NS_ERROR_OUT_OF_MEMORY ;
}
memcpy(mMetaData, data, length) ;
// Generate mInfo
nsresult rv = GenInfo() ;
if(NS_FAILED(rv))
return rv ;
// write through into mDB
rv = mDB->Put(mRecordID, mInfo, mInfoSize) ;
return rv ;
}
NS_IMETHODIMP
nsDiskCacheRecord::GetStoredContentLength(PRUint32 *aStoredContentLength)
{
return mFile->GetFileSize(aStoredContentLength) ;
}
// untill nsIFileSpec::Truncate() is in, we have to do all this ugly stuff
NS_IMETHODIMP
nsDiskCacheRecord::SetStoredContentLength(PRUint32 aStoredContentLength)
{
PRUint32 len = 0 ;
nsresult rv = mFile->GetFileSize(&len) ;
if(NS_FAILED(rv))
return rv ;
if(len < aStoredContentLength)
{
NS_ERROR("Error: can not set filesize to something bigger than itself.\n") ;
return NS_ERROR_FAILURE ;
}
else {
rv = mFile->Truncate(aStoredContentLength) ;
if(NS_FAILED(rv))
return rv ;
mDiskCache->m_StorageInUse -= (len - aStoredContentLength) ;
return NS_OK ;
}
}
NS_IMETHODIMP
nsDiskCacheRecord::Delete(void)
{
if(mNumChannels)
return NS_ERROR_NOT_AVAILABLE ;
PRUint32 len ;
mFile->GetFileSize(&len) ;
nsFileSpec cache_file ;
nsresult rv = mFile->GetFileSpec(&cache_file) ;
if(NS_FAILED(rv))
return NS_ERROR_FAILURE ;
cache_file.Delete(PR_TRUE) ;
// updata the storage size
mDiskCache->m_StorageInUse -= len ;
rv = mDB->Del(mRecordID, mKey, mKeyLength) ;
if(NS_FAILED(rv))
return NS_ERROR_FAILURE ;
else
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecord::GetFilename(nsIFileSpec * *aFilename)
{
if(!aFilename)
return NS_ERROR_NULL_POINTER ;
*aFilename = mFile ;
NS_ADDREF(*aFilename) ;
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecord::NewChannel(nsILoadGroup *loadGroup, nsIChannel **_retval)
{
nsDiskCacheRecordChannel* channel = new nsDiskCacheRecordChannel(this, loadGroup) ;
if(!channel)
return NS_ERROR_OUT_OF_MEMORY ;
nsresult rv = channel->Init() ;
if(NS_FAILED(rv))
return rv ;
NS_ADDREF(channel) ;
*_retval = NS_STATIC_CAST(nsIChannel*, channel) ;
return NS_OK ;
}
//////////////////////////////////////////////////////////////////////////
// nsDiskCacheRecord methods
// file name is represented by a url string. I hope this would be more
// generic
nsresult
nsDiskCacheRecord::GenInfo()
{
if(mInfo)
nsAllocator::Free(mInfo) ;
char* file_url=nsnull ;
PRUint32 name_len ;
mFile->GetURLString(&file_url) ;
name_len = PL_strlen(file_url)+1 ;
mInfoSize = sizeof(PRUint32) ; // checksum for mInfoSize
mInfoSize += sizeof(PRInt32) ; // RecordID
mInfoSize += sizeof(PRUint32) ; // key length
mInfoSize += mKeyLength ; // key
mInfoSize += sizeof(PRUint32) ; // metadata length
mInfoSize += mMetaDataLength ; // metadata
mInfoSize += sizeof(PRUint32) ; // filename length
mInfoSize += name_len ; // filename
void* newInfo = nsAllocator::Alloc(mInfoSize*sizeof(char)) ;
if(!newInfo) {
return NS_ERROR_OUT_OF_MEMORY ;
}
// copy the checksum mInfoSize
char* cur_ptr = NS_STATIC_CAST(char*, newInfo) ;
COPY_INT32(cur_ptr, &mInfoSize) ;
cur_ptr += sizeof(PRUint32) ;
// copy RecordID
COPY_INT32(cur_ptr, &mRecordID) ;
cur_ptr += sizeof(PRInt32) ;
// copy key length
COPY_INT32(cur_ptr, &mKeyLength) ;
cur_ptr += sizeof(PRUint32) ;
// copy key
memcpy(cur_ptr, mKey, mKeyLength) ;
cur_ptr += mKeyLength ;
// copy metadata length
COPY_INT32(cur_ptr, &mMetaDataLength) ;
cur_ptr += sizeof(PRUint32) ;
// copy metadata
memcpy(cur_ptr, mMetaData, mMetaDataLength) ;
cur_ptr += mMetaDataLength ;
// copy file name length
COPY_INT32(cur_ptr, &name_len) ;
cur_ptr += sizeof(PRUint32) ;
// copy file name
memcpy(cur_ptr, file_url, name_len) ;
cur_ptr += name_len ;
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, newInfo) + mInfoSize);
mInfo = newInfo ;
return NS_OK ;
}
/*
* This Method suppose to get all the info from the db record
* and set them to accroding members. the original values
* will all be overwritten. only minimal error checking is performed.
*/
NS_IMETHODIMP
nsDiskCacheRecord::RetrieveInfo(void* aInfo, PRUint32 aInfoLength)
{
// reset everything
if(mInfo) {
nsAllocator::Free(mInfo) ;
mInfo = nsnull ;
}
if(mKey) {
nsAllocator::Free(mKey) ;
mKey = nsnull ;
}
if(mMetaData) {
nsAllocator::Free(mMetaData) ;
mMetaData = nsnull ;
}
char * cur_ptr = NS_STATIC_CAST(char*, aInfo) ;
char* file_url ;
PRUint32 name_len ;
// set mInfoSize
COPY_INT32(&mInfoSize, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
// check this at least
if(mInfoSize != aInfoLength)
return NS_ERROR_FAILURE ;
// set mRecordID
COPY_INT32(&mRecordID, cur_ptr) ;
cur_ptr += sizeof(PRInt32) ;
// set mKeyLength
COPY_INT32(&mKeyLength, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
// set mKey
mKey = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
if(!mKey)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(mKey, cur_ptr, mKeyLength) ;
cur_ptr += mKeyLength ;
PRInt32 id ;
mDB->GetID(mKey, mKeyLength, &id) ;
NS_ASSERTION(id==mRecordID, "\t ++++++ bad record, somethings wrong\n") ;
// set mMetaDataLength
COPY_INT32(&mMetaDataLength, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
// set mMetaData
mMetaData = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
if(!mMetaData)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(mMetaData, cur_ptr, mMetaDataLength) ;
cur_ptr += mMetaDataLength ;
// get mFile name length
COPY_INT32(&name_len, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
// get mFile native name
file_url = NS_STATIC_CAST(char*, nsAllocator::Alloc(name_len*sizeof(char))) ;
if(!file_url)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(file_url, cur_ptr, name_len) ;
cur_ptr += name_len ;
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, aInfo) + mInfoSize);
// create mFile if Init() isn't called
if(!mFile) {
NS_NewFileSpec(getter_AddRefs(mFile));
if(!mFile)
return NS_ERROR_OUT_OF_MEMORY ;
}
// setup mFile
mFile->SetURLString(file_url) ;
return NS_OK ;
}

View File

@@ -0,0 +1,71 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#ifndef _NET_CACHEDDISKDATA_H_
#define _NET_CACHEDDISKDATA_H_
#include "nsINetDataCacheRecord.h"
#include "nsCOMPtr.h"
#include "nsIDBAccessor.h"
#include "prtypes.h"
#include "nsILoadGroup.h"
#include "nsIFileChannel.h"
#include "nsNetDiskCache.h"
class nsDiskCacheRecord : public nsINetDataCacheRecord
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSINETDATACACHERECORD
protected:
nsDiskCacheRecord(nsIDBAccessor* db, nsNetDiskCache* aCache) ;
virtual ~nsDiskCacheRecord() ;
NS_IMETHOD RetrieveInfo(void* aInfo, PRUint32 aInfoLength) ;
NS_IMETHOD Init(const char* key, PRUint32 length, PRInt32 ID) ;
nsresult GenInfo(void) ;
private:
char* mKey ;
PRUint32 mKeyLength ;
PRInt32 mRecordID ;
char* mMetaData ;
PRUint32 mMetaDataLength ;
nsCOMPtr<nsIFileSpec> mFile ;
nsCOMPtr<nsIDBAccessor> mDB ;
void* mInfo ;
PRUint32 mInfoSize ;
PRUint32 mNumChannels ;
nsNetDiskCache* mDiskCache ;
friend class nsDiskCacheRecordChannel ;
friend class nsDBEnumerator ;
friend class nsNetDiskCache ;
} ;
#endif // _NET_CACHEDDISKDATA_H_

View File

@@ -0,0 +1,552 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
/*
* Most of the code are taken from nsFileChannel.
*/
#include "nsDiskCacheRecordChannel.h"
#include "nsIFileTransportService.h"
//#include "nsIIOService.h"
#include "nsIServiceManager.h"
#include "nsIURL.h"
#include "nsIOutputStream.h"
#include "netCore.h"
#include "nsIMIMEService.h"
#include "nsISupportsUtils.h"
//static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID);
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_CID);
// This is copied from nsMemCacheChannel, We should consolidate these two.
class WriteStreamWrapper : public nsIOutputStream
{
public:
WriteStreamWrapper(nsDiskCacheRecordChannel* aChannel,
nsIOutputStream *aBaseStream) ;
virtual ~WriteStreamWrapper() ;
static nsresult
Create(nsDiskCacheRecordChannel* aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* *aWrapper) ;
NS_DECL_ISUPPORTS
NS_DECL_NSIBASESTREAM
NS_DECL_NSIOUTPUTSTREAM
private:
nsDiskCacheRecordChannel* mChannel;
nsCOMPtr<nsIOutputStream> mBaseStream;
} ;
// implement nsISupports
NS_IMPL_ISUPPORTS(WriteStreamWrapper, NS_GET_IID(nsIOutputStream))
WriteStreamWrapper::WriteStreamWrapper(nsDiskCacheRecordChannel* aChannel,
nsIOutputStream *aBaseStream)
: mChannel(aChannel), mBaseStream(aBaseStream)
{
NS_INIT_REFCNT();
NS_ADDREF(mChannel);
}
WriteStreamWrapper::~WriteStreamWrapper()
{
NS_RELEASE(mChannel);
}
nsresult
WriteStreamWrapper::Create(nsDiskCacheRecordChannel*aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* * aWrapper)
{
WriteStreamWrapper *wrapper = new WriteStreamWrapper(aChannel, aBaseStream);
if (!wrapper) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(wrapper);
*aWrapper = wrapper;
return NS_OK;
}
NS_IMETHODIMP
WriteStreamWrapper::Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritten)
{
*aNumWritten = 0;
nsresult rv = mBaseStream->Write(aBuffer, aCount, aNumWritten);
mChannel->NotifyStorageInUse(*aNumWritten);
return rv;
}
NS_IMETHODIMP
WriteStreamWrapper::Flush()
{
return mBaseStream->Flush();
}
NS_IMETHODIMP
WriteStreamWrapper::Close()
{
return mBaseStream->Close();
}
nsDiskCacheRecordChannel::nsDiskCacheRecordChannel(nsDiskCacheRecord *aRecord,
nsILoadGroup *aLoadGroup)
: mRecord(aRecord) ,
mLoadGroup(aLoadGroup)
{
NS_INIT_REFCNT() ;
NS_ADDREF(mRecord);
mRecord->mNumChannels++ ;
}
nsDiskCacheRecordChannel::~nsDiskCacheRecordChannel()
{
mRecord->mNumChannels-- ;
NS_RELEASE(mRecord);
}
// I know that I gave conflicting advice on the issue of file
// transport versus file protocol handler, but I thought that the
// last word was that we would use the raw transport, when I wrote:
//
// > I just thought of an argument for the other side of the coin, i.e. the
// > benefit of *not* reusing the file protocol handler: On the Mac, it's
// > expensive to convert from a string URL to an nsFileSpec, because the Mac
// > is brain-dead and scans every directory on the path to the file. It's
// > cheaper to create a nsFileSpec for a cache file by combining a single,
// > static nsFileSpec that corresponds to the cache directory with the
// > relative path to the cache file (using nsFileSpec's operator +). This
// > operation is optimized on the Mac to avoid the scanning operation.
//
// The Mac guys will eat us alive if we do path string to nsFileSpec
// conversions for every cache file we open.
nsresult
nsDiskCacheRecordChannel::Init(void)
{
nsresult rv = mRecord->mFile->GetFileSpec(&mSpec) ;
#ifdef XP_MAC
// Don't assume we actually created a good file spec
FSSpec theSpec = mSpec.GetFSSpec();
if (!theSpec.name[0]) {
NS_ERROR("failed to create a file spec");
// Since we didn't actually create the file spec
// we return an error
return NS_ERROR_MALFORMED_URI;
}
#endif
return rv ;
}
nsresult
nsDiskCacheRecordChannel::NotifyStorageInUse(PRInt32 aBytesUsed)
{
return mRecord->mDiskCache->m_StorageInUse += aBytesUsed ;
}
// implement nsISupports
NS_IMPL_ISUPPORTS4(nsDiskCacheRecordChannel,
nsIChannel,
nsIRequest,
nsIStreamListener,
nsIStreamObserver)
// implement nsIRequest
NS_IMETHODIMP
nsDiskCacheRecordChannel::IsPending(PRBool *aIsPending)
{
*aIsPending = PR_FALSE ;
if(!mFileTransport)
return NS_OK ;
return mFileTransport->IsPending(aIsPending) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::Cancel(void)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->Cancel() ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::Suspend(void)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->Suspend() ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::Resume(void)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->Resume() ;
}
// implement nsIChannel
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetOriginalURI(nsIURI* *aURI)
{
// FUR - might need to implement this - not sure
return NS_ERROR_NOT_IMPLEMENTED ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetURI(nsIURI * *aURI)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->GetURI(aURI) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::OpenInputStream(PRUint32 aStartPosition,
PRInt32 aReadCount,
nsIInputStream* *aResult)
{
nsresult rv ;
if(mFileTransport)
return NS_ERROR_IN_PROGRESS ;
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv) ;
if(NS_FAILED(rv)) return rv ;
rv = fts->CreateTransport(mSpec, "load", 0, 0, getter_AddRefs(mFileTransport)) ;
if(NS_FAILED(rv))
return rv ;
// we don't need to worry about notification callbacks
rv = mFileTransport->OpenInputStream(aStartPosition, aReadCount, aResult) ;
if(NS_FAILED(rv))
mFileTransport = nsnull ;
return rv ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::OpenOutputStream(PRUint32 startPosition,
nsIOutputStream* *aResult)
{
nsresult rv ;
NS_ENSURE_ARG(aResult) ;
if(mFileTransport)
return NS_ERROR_IN_PROGRESS ;
nsCOMPtr<nsIOutputStream> outputStream ;
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv) ;
if(NS_FAILED(rv)) return rv ;
rv = fts->CreateTransport(mSpec, "load", 0, 0, getter_AddRefs(mFileTransport)) ;
if(NS_FAILED(rv))
return rv ;
// we don't need to worry about notification callbacks
rv = mFileTransport->OpenOutputStream(startPosition, getter_AddRefs(outputStream)) ;
if(NS_FAILED(rv)) {
mFileTransport = nsnull ;
return rv ;
}
return WriteStreamWrapper::Create(this, outputStream, aResult) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::AsyncOpen(nsIStreamObserver *observer,
nsISupports *ctxt)
{
return NS_ERROR_NOT_IMPLEMENTED ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::AsyncRead(PRUint32 aStartPosition,
PRInt32 aReadCount,
nsISupports *aContext,
nsIStreamListener *aListener)
{
nsresult rv ;
if(mFileTransport)
return NS_ERROR_IN_PROGRESS ;
mRealListener = aListener;
nsCOMPtr<nsIStreamListener> tempListener = this;
if (mLoadGroup) {
nsCOMPtr<nsILoadGroupListenerFactory> factory;
//
// Create a load group "proxy" listener...
//
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
if (factory) {
nsIStreamListener *newListener;
rv = factory->CreateLoadGroupListener(mRealListener, &newListener);
if (NS_SUCCEEDED(rv)) {
mRealListener = newListener;
NS_RELEASE(newListener);
}
}
rv = mLoadGroup->AddChannel(this, nsnull);
if (NS_FAILED(rv)) return rv;
}
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = fts->CreateTransport(mSpec, "load", 0, 0, getter_AddRefs(mFileTransport));
if (NS_FAILED(rv)) return rv;
// no callbacks
rv = mFileTransport->AsyncRead(aStartPosition,
aReadCount,
aContext,
tempListener);
if (NS_FAILED(rv)) {
// release the transport so that we don't think we're in progress
mFileTransport = nsnull;
}
return rv;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::AsyncWrite(nsIInputStream *fromStream,
PRUint32 startPosition,
PRInt32 writeCount,
nsISupports *ctxt,
nsIStreamObserver *observer)
{
/*
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->AsyncWrite(fromStream,
startPosition,
writeCount,
ctxt,
observer) ;
*/
// I can't do this since the write is not monitored, and I won't be
// able to updata the storage.
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
#define DUMMY_TYPE "text/html"
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetContentType(char * *aContentType)
{
nsresult rv ;
if (mSpec.IsDirectory()) {
*aContentType = nsCRT::strdup("application/http-index-format");
return *aContentType ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
else {
// I wish I can make this simplier
char* urlStr ;
mRecord->mFile->GetURLString(&urlStr) ;
// file: URLs (currently) have no additional structure beyond that provided by standard
// URLs, so there is no "outer" given to CreateInstance
nsCOMPtr<nsIURI> url;
rv = nsComponentManager::CreateInstance(kStandardURLCID, nsnull,
NS_GET_IID(nsIURI),
//(void**)&url);
getter_AddRefs(url)) ;
if (NS_FAILED(rv)) return rv;
rv = url->SetSpec((char*)urlStr);
if (NS_FAILED(rv))
return rv;
NS_WITH_SERVICE(nsIMIMEService, MIMEService, kMIMEServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = MIMEService->GetTypeFromURI(url, aContentType);
if (NS_SUCCEEDED(rv)) return rv;
}
// if all else fails treat it as text/html?
*aContentType = nsCRT::strdup(DUMMY_TYPE);
if (!*aContentType) {
return NS_ERROR_OUT_OF_MEMORY;
} else {
return NS_OK;
}
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetContentLength(PRInt32 *aContentLength)
{
nsresult rv;
PRUint32 length;
rv = mRecord->mFile->GetFileSize(&length);
if (NS_SUCCEEDED(rv)) {
*aContentLength = (PRInt32)length;
} else {
*aContentLength = -1;
}
return rv;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetOwner(nsISupports* *aOwner)
{
*aOwner = mOwner.get() ;
NS_IF_ADDREF(*aOwner) ;
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::SetOwner(nsISupports* aOwner)
{
mOwner = aOwner ;
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
return NS_OK;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
////////////////////////////////////////////////////////////////////////////////
// nsIStreamListener methods:
////////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsDiskCacheRecordChannel::OnStartRequest(nsIChannel* transportChannel, nsISupports* context)
{
NS_ASSERTION(mRealListener, "No listener...");
return mRealListener->OnStartRequest(this, context);
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::OnStopRequest(nsIChannel* transportChannel, nsISupports* context,
nsresult aStatus, const PRUnichar* aMsg)
{
nsresult rv;
rv = mRealListener->OnStopRequest(this, context, aStatus, aMsg);
if (mLoadGroup) {
if (NS_SUCCEEDED(rv)) {
mLoadGroup->RemoveChannel(this, context, aStatus, aMsg);
}
}
// Release the reference to the consumer stream listener...
mRealListener = null_nsCOMPtr();
mFileTransport = null_nsCOMPtr();
return rv;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::OnDataAvailable(nsIChannel* transportChannel, nsISupports* context,
nsIInputStream *aIStream, PRUint32 aSourceOffset,
PRUint32 aLength)
{
nsresult rv;
rv = mRealListener->OnDataAvailable(this, context, aIStream,
aSourceOffset, aLength);
//
// If the connection is being aborted cancel the transport. This will
// insure that the transport will go away even if it is blocked waiting
// for the consumer to empty the pipe...
//
if (NS_FAILED(rv)) {
mFileTransport->Cancel();
}
return rv;
}

View File

@@ -0,0 +1,76 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#ifndef _ns_DiskCacheRecordChannel_h_
#define _ns_DiskCacheRecordChannel_h_
#include "nsIChannel.h"
#include "nsCOMPtr.h"
#include "nsDiskCacheRecord.h"
#include "nsIStreamListener.h"
/*
* This class is plagiarized from nsMemCacheChannel
*/
class nsDiskCacheRecordChannel : public nsIChannel,
public nsIStreamListener
{
public:
nsDiskCacheRecordChannel(nsDiskCacheRecord *aRecord, nsILoadGroup *aLoadGroup);
virtual ~nsDiskCacheRecordChannel() ;
// Declare nsISupports methods
NS_DECL_ISUPPORTS
// Declare nsIRequest methods
NS_DECL_NSIREQUEST
// Declare nsIChannel methods
NS_DECL_NSICHANNEL
// Declare nsIStreamObserver methods
NS_DECL_NSISTREAMOBSERVER
// Declare nsIStreamListener methods
NS_DECL_NSISTREAMLISTENER
nsresult Init(void) ;
private:
nsresult NotifyStorageInUse(PRInt32 aBytesUsed) ;
nsDiskCacheRecord* mRecord ;
nsCOMPtr<nsILoadGroup> mLoadGroup ;
nsCOMPtr<nsISupports> mOwner ;
nsCOMPtr<nsIChannel> mFileTransport ;
nsFileSpec mSpec ;
nsCOMPtr<nsIStreamListener> mRealListener;
friend class WriteStreamWrapper ;
} ;
#endif // _ns_DiskCacheRecordChannel_h_

View File

@@ -0,0 +1,66 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#ifndef _NS_IDBACCESSOR_H_
#define _NS_IDBACCESSOR_H_
#include "nsISupports.h"
#include "nsIFileSpec.h"
// nsIDBAccessorIID {6AADD4D0-7785-11d3-87FE-000629D01344}
#define NS_IDBACCESSOR_IID \
{ 0x6aadd4d0, 0x7785, 0x11d3, \
{0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44}}
// nsDBAccessorCID {6AADD4D1-7785-11d3-87FE-000629D01344}
#define NS_DBACCESSOR_CID \
{ 0x6aadd4d1, 0x7785, 0x11d3, \
{ 0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44 }}
class nsIDBAccessor : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDBACCESSOR_IID)
NS_IMETHOD Init(nsIFileSpec* DBFile) = 0 ;
NS_IMETHOD Shutdown(void) = 0 ;
NS_IMETHOD Put(PRInt32 aID, void* anEntry, PRUint32 aLength) = 0 ;
NS_IMETHOD Get(PRInt32 aID, void** anEntry, PRUint32 *aLength) = 0 ;
NS_IMETHOD Del(PRInt32 aID, void* anEntry, PRUint32 aLength) = 0 ;
NS_IMETHOD GetID(const char* key, PRUint32 length, PRInt32* aID) = 0 ;
NS_IMETHOD EnumEntry(void* *anEntry, PRUint32* aLength, PRBool bReset) = 0 ;
NS_IMETHOD GetDBFilesize(PRUint32* aSize) = 0 ;
NS_IMETHOD GetSpecialEntry(void** anEntry, PRUint32 *aLength) = 0 ;
NS_IMETHOD SetSpecialEntry(void* anEntry, PRUint32 aLength) = 0 ;
} ;
#endif // _NS_IDBACCESSOR_H_

View File

@@ -0,0 +1,704 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#include "nsNetDiskCache.h"
#include "nscore.h"
#include "plstr.h"
#include "prprf.h"
#include "prtypes.h"
#include "prio.h"
#include "prsystem.h" // Directory Seperator
#include "plhash.h"
#include "prclist.h"
#include "prmem.h"
#include "prlog.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIPref.h"
#include "mcom_db.h"
#include "nsDBEnumerator.h"
#include "nsDiskCacheRecord.h"
#include "netCore.h"
#if !defined(IS_LITTLE_ENDIAN) && !defined(IS_BIG_ENDIAN)
ERROR! Must have a byte order
#endif
#ifdef IS_LITTLE_ENDIAN
#define COPY_INT32(_a,_b) memcpy(_a, _b, sizeof(int32))
#else
#define COPY_INT32(_a,_b) /* swap */ \
do { \
((char *)(_a))[0] = ((char *)(_b))[3]; \
((char *)(_a))[1] = ((char *)(_b))[2]; \
((char *)(_a))[2] = ((char *)(_b))[1]; \
((char *)(_a))[3] = ((char *)(_b))[0]; \
} while(0)
#endif
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID) ;
static NS_DEFINE_CID(kDBAccessorCID, NS_DBACCESSOR_CID) ;
static const PRUint32 DISK_CACHE_SIZE_DEFAULT = 5*1024*1024 ; // 5MB
static const char * const DISK_CACHE_PREF = "browser.cache.disk_cache_size";
static const char * const CACHE_DIR_PREF = "browser.cache.directory";
class nsDiskCacheRecord ;
nsNetDiskCache::nsNetDiskCache() :
m_Enabled(PR_TRUE) ,
m_NumEntries(0) ,
m_pNextCache(0) ,
m_pDiskCacheFolder(0) ,
m_StorageInUse(0) ,
m_DB(0) ,
m_DBCorrupted(PR_FALSE)
{
// set it to INF for now
m_MaxEntries = (PRUint32)-1 ;
NS_INIT_REFCNT();
}
nsNetDiskCache::~nsNetDiskCache()
{
SetSpecialEntry() ;
NS_IF_RELEASE(m_DB) ;
// FUR
// I think that, eventually, we also want a distinguished key in the DB which
// means "clean cache shutdown". You clear this flag when the db is first
// opened and set it just before the db is closed. If the db wasn't shutdown
// cleanly in a prior session, i.e. because the app crashed, on startup you
// scan all the individual files in directories and look for "orphans",
// i.e. cache files which don't have corresponding entries in the db. That's
// also when storage-in-use and number of entries would be recomputed.
//
// We don't necessarily need all this functionality immediately, though.
if(m_DBCorrupted) {
nsFileSpec cacheFolder ;
m_pDiskCacheFolder->GetFileSpec(&cacheFolder) ;
char nameInt[6] ;
for(nsDirectoryIterator di(cacheFolder, PR_FALSE); di.Exists(); di++) {
char* filename = di.Spec().GetLeafName() ;
char* pname = nameInt ;
pname = PL_strncpyz(pname, filename, 6) ;
if(PL_strcmp(pname, "trash") == 0)
RemoveFolder(di.Spec()) ;
nsCRT::free(filename) ;
}
}
}
NS_IMETHODIMP
nsNetDiskCache::Init(void)
{
nsresult rv ;
// don't initialize if no cache folder is set.
if(!m_pDiskCacheFolder) return NS_OK ;
if(!m_DB) {
m_DB = new nsDBAccessor() ;
if(!m_DB)
return NS_ERROR_OUT_OF_MEMORY ;
else
NS_ADDREF(m_DB) ;
}
// create cache sub directories
nsCOMPtr<nsIFileSpec> cacheSubDir;
rv = NS_NewFileSpec(getter_AddRefs(cacheSubDir));
for (int i=0; i < 32; i++) {
rv = cacheSubDir->FromFileSpec(m_pDiskCacheFolder) ;
if(NS_FAILED(rv))
return rv ;
char dirName[3];
PR_snprintf (dirName, 3, "%0.2x", i);
cacheSubDir->AppendRelativeUnixPath (dirName) ;
CreateDir(cacheSubDir);
}
return InitDB() ;
}
NS_IMETHODIMP
nsNetDiskCache::InitDB(void)
{
nsresult rv ;
if(!m_DBFile) {
NS_NewFileSpec(getter_AddRefs(m_DBFile)) ;
if(!m_DBFile)
return NS_ERROR_OUT_OF_MEMORY ;
}
rv = m_DBFile->FromFileSpec(m_pDiskCacheFolder) ;
if(NS_FAILED(rv))
return rv ;
m_DBFile->AppendRelativeUnixPath("cache.db") ;
rv = m_DB->Init(m_DBFile) ;
if(rv == NS_ERROR_FAILURE) {
// try recovery if error
DBRecovery() ;
}
rv = GetSpecialEntry() ;
if(rv == NS_ERROR_FAILURE) {
// try recovery if error
DBRecovery() ;
}
return rv ;
}
//////////////////////////////////////////////////////////////////////////
// nsISupports methods
NS_IMPL_ISUPPORTS3(nsNetDiskCache,
nsINetDataDiskCache,
nsINetDataCache,
nsISupports)
///////////////////////////////////////////////////////////////////////////
// nsINetDataCache Method
NS_IMETHODIMP
nsNetDiskCache::GetDescription(PRUnichar* *aDescription)
{
nsAutoString description("Disk Cache") ;
*aDescription = description.ToNewUnicode() ;
if(!*aDescription)
return NS_ERROR_OUT_OF_MEMORY ;
return NS_OK ;
}
/* don't alloc mem for nsICachedNetData.
* RecordID is generated using the same scheme in nsCacheDiskData,
* see GetCachedNetData() for detail.
*/
NS_IMETHODIMP
nsNetDiskCache::Contains(const char* key, PRUint32 length, PRBool *_retval)
{
*_retval = PR_FALSE ;
NS_ASSERTION(m_DB, "no db.") ;
PRInt32 id = 0 ;
nsresult rv = m_DB->GetID(key, length, &id) ;
if(NS_FAILED(rv)) {
// try recovery if error
DBRecovery() ;
return rv ;
}
void* info = 0 ;
PRUint32 info_size = 0 ;
rv = m_DB->Get(id, &info, &info_size) ;
if(NS_SUCCEEDED(rv) && info)
*_retval = PR_TRUE ;
if(NS_FAILED(rv)) {
// try recovery if error
DBRecovery() ;
}
return rv ;
}
/* regardless if it's cached or not, a copy of nsNetDiskCache would
* always be returned. so release it appropriately.
* if mem alloced, updata m_NumEntries also.
* for now, the new nsCachedNetData is not written into db yet since
* we have nothing to write.
*/
NS_IMETHODIMP
nsNetDiskCache::GetCachedNetData(const char* key, PRUint32 length, nsINetDataCacheRecord **_retval)
{
NS_ASSERTION(m_DB, "no db.") ;
nsresult rv = 0 ;
if (!_retval)
return NS_ERROR_NULL_POINTER ;
*_retval = nsnull ;
PRInt32 id = 0 ;
rv = m_DB->GetID(key, length, &id) ;
if(NS_FAILED(rv)) {
// try recovery if error
DBRecovery() ;
return rv ;
}
// construct an empty record
nsDiskCacheRecord* newRecord = new nsDiskCacheRecord(m_DB, this) ;
if(!newRecord)
return NS_ERROR_OUT_OF_MEMORY ;
rv = newRecord->Init(key, length, id) ;
if(NS_FAILED(rv)) {
delete newRecord ;
return rv ;
}
NS_ADDREF(newRecord) ; // addref for _retval
*_retval = (nsINetDataCacheRecord*) newRecord ;
void* info = 0 ;
PRUint32 info_size = 0 ;
rv = m_DB->Get(id, &info, &info_size) ;
if(NS_SUCCEEDED(rv) && info) {
// this is a previously cached record
nsresult r1 ;
r1 = newRecord->RetrieveInfo(info, info_size) ;
if(NS_SUCCEEDED(rv))
return NS_OK ;
else {
// probably a bad one
NS_RELEASE(newRecord) ;
*_retval = nsnull ;
return r1;
}
} else if (NS_SUCCEEDED(rv) && !info) {
// this is a new record.
m_NumEntries ++ ;
return NS_OK ;
} else {
// database error.
DBRecovery() ;
return rv ;
}
}
/* get an nsICachedNetData, mem needs to be de-alloced if not found. */
NS_IMETHODIMP
nsNetDiskCache::GetCachedNetDataByID(PRInt32 RecordID, nsINetDataCacheRecord **_retval)
{
NS_ASSERTION(m_DB, "no db.") ;
if (!_retval)
return NS_ERROR_NULL_POINTER ;
*_retval = nsnull ;
nsresult rv ;
void* info = 0 ;
PRUint32 info_size = 0 ;
rv = m_DB->Get(RecordID, &info, &info_size) ;
if(NS_SUCCEEDED(rv) && info) {
// construct an empty record if only found in db
nsDiskCacheRecord* newRecord = new nsDiskCacheRecord(m_DB, this) ;
if(!newRecord)
return NS_ERROR_OUT_OF_MEMORY ;
NS_ADDREF(newRecord) ; // addref for _retval
rv = newRecord->RetrieveInfo(info, info_size) ;
if(NS_SUCCEEDED(rv)) {
*_retval = (nsINetDataCacheRecord*) newRecord ;
return NS_OK ;
}
else {
// bad record, I guess
NS_RELEASE(newRecord) ; // release if bad things happen
return rv ;
}
} else {
NS_ERROR("Error: RecordID not in DB\n") ;
DBRecovery() ;
return rv ;
}
}
NS_IMETHODIMP
nsNetDiskCache::GetEnabled(PRBool *aEnabled)
{
*aEnabled = m_Enabled ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::SetEnabled(PRBool aEnabled)
{
m_Enabled = aEnabled ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::GetFlags(PRUint32 *aFlags)
{
*aFlags = FILE_PER_URL_CACHE;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::GetNumEntries(PRUint32 *aNumEntries)
{
*aNumEntries = m_NumEntries ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::GetMaxEntries(PRUint32 *aMaxEntries)
{
*aMaxEntries = m_MaxEntries ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::NewCacheEntryIterator(nsISimpleEnumerator **_retval)
{
NS_ASSERTION(m_DB, "no db.") ;
if(!_retval)
return NS_ERROR_NULL_POINTER ;
*_retval = nsnull ;
nsISimpleEnumerator* enumerator = new nsDBEnumerator(m_DB, this) ;
if(enumerator) {
NS_ADDREF(enumerator) ;
*_retval = enumerator ;
return NS_OK ;
}
else
return NS_ERROR_OUT_OF_MEMORY ;
}
NS_IMETHODIMP
nsNetDiskCache::GetNextCache(nsINetDataCache * *aNextCache)
{
if(!aNextCache)
return NS_ERROR_NULL_POINTER ;
*aNextCache = m_pNextCache ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::SetNextCache(nsINetDataCache *aNextCache)
{
m_pNextCache = aNextCache ;
return NS_OK ;
}
// db size can always be measured at the last minute. Since it's hard
// to know before hand.
NS_IMETHODIMP
nsNetDiskCache::GetStorageInUse(PRUint32 *aStorageInUse)
{
NS_ASSERTION(m_DB, "no db.") ;
PRUint32 total_size = m_StorageInUse ;
/*
PRUint32 len = 0 ;
// add the size of the db.
m_DB->GetDBFilesize(&len) ;
total_size += len ;
*/
// we need size in kB
total_size = total_size >> 10 ;
*aStorageInUse = total_size ;
return NS_OK ;
}
/*
* The whole cache dirs can be whiped clean since all the cache
* files are resides in seperate hashed dirs. It's safe to do so.
*/
NS_IMETHODIMP
nsNetDiskCache::RemoveAll(void)
{
NS_ASSERTION(m_DB, "no db.") ;
NS_ASSERTION(m_pDiskCacheFolder, "no cache folder.") ;
// remove all the sub folders
nsFileSpec cacheSubDir;
for (int i=0; i < 32; i++) {
m_pDiskCacheFolder->GetFileSpec(&cacheSubDir) ;
char dirName[3];
PR_snprintf (dirName, 3, "%0.2x", i);
cacheSubDir += dirName ;
RemoveFolder(cacheSubDir) ;
}
// don't forget the db file itself
m_DB->Shutdown() ;
nsFileSpec dbfile ;
m_DBFile->GetFileSpec(&dbfile) ;
dbfile.Delete(PR_TRUE) ;
// reinitilize
return Init() ;
}
//////////////////////////////////////////////////////////////////
// nsINetDataDiskCache methods
NS_IMETHODIMP
nsNetDiskCache::GetDiskCacheFolder(nsIFileSpec * *aDiskCacheFolder)
{
*aDiskCacheFolder = nsnull ;
NS_ASSERTION(m_pDiskCacheFolder, "no cache folder.") ;
*aDiskCacheFolder = m_pDiskCacheFolder ;
NS_ADDREF(*aDiskCacheFolder) ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::SetDiskCacheFolder(nsIFileSpec * aDiskCacheFolder)
{
if(!m_pDiskCacheFolder) {
NS_NewFileSpec(getter_AddRefs(m_pDiskCacheFolder));
if(!m_pDiskCacheFolder)
return NS_ERROR_OUT_OF_MEMORY ;
m_pDiskCacheFolder = aDiskCacheFolder ;
return Init() ;
}
else {
char *newfolder, *oldfolder ;
m_pDiskCacheFolder->GetNativePath(&oldfolder) ;
aDiskCacheFolder->GetNativePath(&newfolder) ;
if(PL_strcmp(newfolder, oldfolder) != 0) {
m_pDiskCacheFolder = aDiskCacheFolder ;
// do we need to blow away old cache before building a new one?
// return RemoveAll() ;
m_DB->Shutdown() ;
return Init() ;
} else
return NS_OK ;
}
}
//////////////////////////////////////////////////////////////////
// nsNetDiskCache methods
// create a directory (recursively)
NS_IMETHODIMP
nsNetDiskCache::CreateDir(nsIFileSpec* dir_spec)
{
PRBool does_exist ;
nsCOMPtr<nsIFileSpec> p_spec ;
dir_spec->Exists(&does_exist) ;
if(does_exist)
return NS_OK ;
nsresult rv = dir_spec->GetParent(getter_AddRefs(p_spec)) ;
if(NS_FAILED(rv))
return rv ;
p_spec->Exists(&does_exist) ;
if(!does_exist) {
CreateDir(p_spec) ;
rv = dir_spec->CreateDir() ;
if(NS_FAILED(rv))
return rv ;
}
else {
rv = dir_spec->CreateDir() ;
if(NS_FAILED(rv))
return rv ;
}
return NS_OK ;
}
// We can't afford to make a *separate* pass over the whole db on every
// startup, just to figure out m_NumEntries and m_StorageInUse. (This is a
// several second operation on a large db). We'll likely need to store
// distinguished keys in the db that contain these values and update them
// incrementally, except when failure to shut down the db cleanly is detected.
NS_IMETHODIMP
nsNetDiskCache::GetSpecialEntry(void)
{
void* pInfo ;
PRUint32 InfoSize ;
nsresult rv = m_DB->GetSpecialEntry(&pInfo, &InfoSize) ;
if(NS_FAILED(rv))
return rv ;
if(!pInfo && InfoSize == 0) {
// must be a new DB
m_NumEntries = 0 ;
m_StorageInUse = 0 ;
}
else {
char * cur_ptr = NS_STATIC_CAST(char*, pInfo) ;
// get m_NumEntries
COPY_INT32(&m_NumEntries, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
// get m_StorageInUse
COPY_INT32(&m_StorageInUse, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, pInfo) + InfoSize);
}
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::SetSpecialEntry(void)
{
PRUint32 InfoSize ;
InfoSize = sizeof m_NumEntries ;
InfoSize += sizeof m_StorageInUse ;
void* pInfo = nsAllocator::Alloc(InfoSize*sizeof(char)) ;
if(!pInfo)
return NS_ERROR_OUT_OF_MEMORY ;
char* cur_ptr = NS_STATIC_CAST(char*, pInfo) ;
COPY_INT32(cur_ptr, &m_NumEntries) ;
cur_ptr += sizeof(PRUint32) ;
COPY_INT32(cur_ptr, &m_StorageInUse) ;
cur_ptr += sizeof(PRUint32) ;
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, pInfo) + InfoSize);
return m_DB->SetSpecialEntry(pInfo, InfoSize) ;
}
// this routine will be called everytime we have a db corruption.
// m_DB will be re-initialized, m_StorageInUse and m_NumEntries will
// be reset.
NS_IMETHODIMP
nsNetDiskCache::DBRecovery(void)
{
// rename all the sub cache dirs and remove them later during dtor.
nsresult rv = RenameCacheSubDirs() ;
if(NS_FAILED(rv))
return rv ;
// remove corrupted db file, don't care if db->shutdown fails or not.
m_DB->Shutdown() ;
nsFileSpec dbfile ;
m_DBFile->GetFileSpec(&dbfile) ;
dbfile.Delete(PR_TRUE) ;
// make sure it's not there any more
PRBool exists = dbfile.Exists() ;
if(exists) {
NS_ERROR("can't remove old db.") ;
return NS_ERROR_FAILURE ;
}
// reinitilize DB
return InitDB() ;
}
// this routine will add string "trash" to current CacheSubDir names.
// e.g. 00->trash00, 1f->trash1f. and update the m_DBCorrupted.
NS_IMETHODIMP
nsNetDiskCache::RenameCacheSubDirs(void)
{
nsCOMPtr<nsIFileSpec> cacheSubDir;
nsresult rv = NS_NewFileSpec(getter_AddRefs(cacheSubDir)) ;
for (int i=0; i < 32; i++) {
rv = cacheSubDir->FromFileSpec(m_pDiskCacheFolder) ;
if(NS_FAILED(rv))
return rv ;
char oldName[3], newName[8];
PR_snprintf(oldName, 3, "%0.2x", i) ;
cacheSubDir->AppendRelativeUnixPath(oldName) ;
// re-name the directory
PR_snprintf(newName, 8, "trash%0.2x", i) ;
rv = cacheSubDir->Rename(newName) ;
if(NS_FAILED(rv))
// TODO, error checking
return NS_ERROR_FAILURE ;
}
// update m_DBCorrupted
m_DBCorrupted = PR_TRUE ;
return NS_OK ;
}
// this routine is used by dtor and RemoveAll() to clean up dirs.
NS_IMETHODIMP
nsNetDiskCache::RemoveFolder(nsFileSpec aFolder)
{
for(nsDirectoryIterator di(aFolder, PR_FALSE); di.Exists(); di++) {
di.Spec().Delete(PR_TRUE) ;
}
aFolder.Delete(PR_FALSE) ; // recursive delete
return NS_OK ;
}

View File

@@ -0,0 +1,91 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
/*
* This file is part of filecache implementation.
*
* nsNetDiskCache is the main disk cache module that will create
* the cache database, and then store and retrieve nsDiskCacheRecord
* objects from it. It also contains some basic error recovery procedure.
*/
#ifndef __gen_nsNetDiskCache_h__
#define __gen_nsNetDiskCache_h__
#include "nsINetDataDiskCache.h"
#include "nsNetDiskCacheCID.h"
#include "nsCOMPtr.h"
#include "nsIPref.h"
#include "nsDBAccessor.h"
class nsIURI; /* forward decl */
class nsICachedNetData; /* forward decl */
class nsISimpleEnumerator; /* forward decl */
class nsIFileSpec; /* forward decl */
/* starting interface: nsNetDiskCache */
class nsNetDiskCache : public nsINetDataDiskCache {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSINETDATACACHE
NS_DECL_NSINETDATADISKCACHE
NS_IMETHOD Init(void) ;
nsNetDiskCache() ;
virtual ~nsNetDiskCache() ;
protected:
NS_IMETHOD InitDB(void) ;
NS_IMETHOD CreateDir(nsIFileSpec* dir_spec) ;
NS_IMETHOD GetSpecialEntry(void) ;
NS_IMETHOD SetSpecialEntry(void) ;
NS_IMETHOD RenameCacheSubDirs(void) ;
NS_IMETHOD DBRecovery(void) ;
NS_IMETHOD RemoveFolder(nsFileSpec aFolder) ;
private:
PRBool m_Enabled ;
PRUint32 m_NumEntries ;
nsCOMPtr<nsINetDataCache> m_pNextCache ;
nsCOMPtr<nsIFileSpec> m_pDiskCacheFolder ;
nsCOMPtr<nsIFileSpec> m_DBFile ;
PRUint32 m_MaxEntries ;
PRUint32 m_StorageInUse ;
nsIDBAccessor* m_DB ;
// this is used to indicate a db corruption
PRBool m_DBCorrupted ;
friend class nsDiskCacheRecord ;
friend class nsDiskCacheRecordChannel ;
friend class nsDBEnumerator ;
} ;
#endif /* __gen_nsNetDiskCache_h__ */

View File

@@ -0,0 +1,32 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#ifndef _nsNetDiskCacheCID_h_
#define _nsNetDiskCacheCID_h_
#define NS_NETDISKCACHE_CID_STR "ECFEEA00-7201-11d3-87FE-000629D01344"
#define NS_NETDISKCACHE_CID \
{ 0xecfeea00, 0x7201, 0x11d3, \
{ 0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44 }}
#endif /* _nsNetDiskCacheCID_h_ */

View File

@@ -0,0 +1,50 @@
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
REQUIRES = libreg xpcom
CPPSRCS = \
diskcache.cpp \
$(NULL)
SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=)
ifdef NO_LD_ARCHIVE_FLAGS
LOST_SYM_LIBS = -lxpcomds_s -lxptinfo -lmozreg_s
endif
LIBS = \
-lmozjs \
-lxpcom \
-lmozdbm_s \
$(MOZ_NECKO_UTIL_LIBS) \
$(LOST_SYM_LIBS) \
$(NSPR_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = -I$(srcdir)/..
DEFINES += -DUSE_NSREG -DCACHE

View File

@@ -0,0 +1,836 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsIStreamListener.h"
#include "nsIStreamObserver.h"
#include "nsIServiceManager.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIEventQueue.h"
#include "nsIEventQueueService.h"
#include "nsIChannel.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include <stdio.h>
#include <unistd.h>
#include "nsINetDataCache.h"
#include "nsINetDataCacheRecord.h"
//#include "nsMemCacheCID.h"
#include "nsNetDiskCache.h"
#include "nsIPref.h"
#include "prenv.h"
#include "nsIFileStream.h"
// Number of test entries to be placed in the cache
#define NUM_CACHE_ENTRIES 250
// Cache content stream length will have random length between zero and
// MAX_CONTENT_LENGTH bytes
#define MAX_CONTENT_LENGTH 20000
// Length of random-data cache entry key
#define CACHE_KEY_LENGTH 15
// Length of random-data cache entry meta-data
#define CACHE_METADATA_LENGTH 100
//static NS_DEFINE_CID(kMemCacheCID, NS_MEM_CACHE_FACTORY_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kDiskCacheCID, NS_NETDISKCACHE_CID) ;
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
static NS_DEFINE_IID(kIPrefIID, NS_IPREF_IID);
// Mapping from test case number to RecordID
static PRInt32 recordID[NUM_CACHE_ENTRIES];
static PRInt32
mapRecordIdToTestNum(PRInt32 aRecordID)
{
int i;
for (i = 0; i < NUM_CACHE_ENTRIES; i++) {
if (recordID[i] == aRecordID)
return i;
}
return -1;
}
// A supply of stream data to either store or compare with
class nsITestDataStream {
public:
virtual ~nsITestDataStream() {};
virtual PRUint32 Next() = 0;
virtual void Read(char* aBuf, PRUint32 aCount) = 0;
virtual PRBool Match(char* aBuf, PRUint32 aCount) = 0;
virtual void Skip(PRUint32 aCount) = 0;
};
// A reproducible stream of random data.
class RandomStream : public nsITestDataStream {
public:
RandomStream(PRUint32 aSeed) {
mStartSeed = mState = aSeed;
}
PRUint32 GetStartSeed() {
return mStartSeed;
}
PRUint32 Next() {
mState = 1103515245 * mState + 12345;
return mState;
}
void Read(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
*aBuf++ = Next();
}
}
PRBool
Match(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
if (*aBuf++ != (char)(Next() & 0xff))
return PR_FALSE;
}
return PR_TRUE;
}
void
Skip(PRUint32 aCount) {
while (aCount--)
Next();
}
protected:
PRUint32 mState;
PRUint32 mStartSeed;
};
// A stream of data that increments on each byte that is read, modulo 256
class CounterStream : public nsITestDataStream {
public:
CounterStream(PRUint32 aSeed) {
mStartSeed = mState = aSeed;
}
PRUint32 GetStartSeed() {
return mStartSeed;
}
PRUint32 Next() {
mState += 1;
mState &= 0xff;
return mState;
}
void Read(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
*aBuf++ = Next();
}
}
PRBool
Match(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
if (*aBuf++ != (char)Next())
return PR_FALSE;
}
return PR_TRUE;
}
void
Skip(PRUint32 aCount) {
mState += aCount;
mState &= 0xff;
}
protected:
PRUint32 mState;
PRUint32 mStartSeed;
};
static int gNumReaders = 0;
static PRUint32 gTotalBytesRead = 0;
static PRUint32 gTotalDuration = 0;
class nsReader : public nsIStreamListener {
public:
NS_DECL_ISUPPORTS
nsReader()
: mStartTime(0), mBytesRead(0)
{
NS_INIT_REFCNT();
gNumReaders++;
}
virtual ~nsReader() {
delete mTestDataStream;
gNumReaders--;
}
nsresult
Init(nsIChannel *aChannel, nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
mChannel = aChannel;
mTestDataStream = aRandomStream;
mExpectedStreamLength = aExpectedStreamLength;
mRefCnt = 1;
return NS_OK;
}
NS_IMETHOD OnStartRequest(nsIChannel* channel,
nsISupports* context) {
mStartTime = PR_IntervalNow();
return NS_OK;
}
NS_IMETHOD OnDataAvailable(nsIChannel* channel,
nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength) {
char buf[1025];
while (aLength > 0) {
PRUint32 amt;
PRBool match;
aIStream->Read(buf, sizeof buf, &amt);
if (amt == 0) break;
aLength -= amt;
mBytesRead += amt;
match = mTestDataStream->Match(buf, amt);
NS_ASSERTION(match, "Stored data was corrupted on read");
}
return NS_OK;
}
NS_IMETHOD OnStopRequest(nsIChannel* channel,
nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg) {
PRIntervalTime endTime;
PRIntervalTime duration;
endTime = PR_IntervalNow();
duration = (endTime - mStartTime);
if (NS_FAILED(aStatus)) printf("channel failed.\n");
// printf("read %d bytes\n", mBytesRead);
NS_ASSERTION(mBytesRead == mExpectedStreamLength,
"Stream in cache is wrong length");
gTotalBytesRead += mBytesRead;
gTotalDuration += duration;
// Release channel
mChannel = 0;
return NS_OK;
}
protected:
PRIntervalTime mStartTime;
PRUint32 mBytesRead;
nsITestDataStream* mTestDataStream;
PRUint32 mExpectedStreamLength;
nsCOMPtr<nsIChannel> mChannel;
};
NS_IMPL_ISUPPORTS2(nsReader, nsIStreamListener, nsIStreamObserver)
static nsIEventQueue* eventQueue;
nsresult
InitQueue() {
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue service");
rv = eventQService->CreateThreadEventQueue();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create event queue");
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQueue);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue for main thread");
return NS_OK;
}
// Process events until all streams are OnStopRequest'ed
nsresult
WaitForEvents() {
while (gNumReaders) {
eventQueue->ProcessPendingEvents();
}
return NS_OK;
}
// Read data for a single cache record and compare against testDataStream
nsresult
TestReadStream(nsINetDataCacheRecord *record, nsITestDataStream *testDataStream,
PRUint32 expectedStreamLength)
{
nsCOMPtr<nsIChannel> channel;
nsresult rv;
PRUint32 actualContentLength;
rv = record->NewChannel(0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = record->GetStoredContentLength(&actualContentLength);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(actualContentLength == expectedStreamLength,
"nsINetDataCacheRecord::GetContentLength() busted ?");
nsReader *reader = new nsReader;
reader->AddRef();
rv = reader->Init(channel, testDataStream, expectedStreamLength);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = channel->AsyncRead(0, -1, 0, reader);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
reader->Release();
return NS_OK;
}
// Check that records can be retrieved using their record-ID, in addition
// to using the opaque key.
nsresult
TestRecordID(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
RandomStream *randomStream;
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char *metaData;
PRUint32 testNum;
PRBool match;
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
rv = cache->GetCachedNetDataByID(recordID[testNum], getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't obtain record using record ID");
// Match against previously stored meta-data
rv = record->GetMetaData(&metaDataLength, &metaData);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
match = randomStream->Match(metaData, metaDataLength);
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
nsAllocator::Free(metaData);
delete randomStream;
}
return NS_OK;
}
// Check that all cache entries in the database are enumerated and that
// no duplicates appear.
nsresult
TestEnumeration(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
nsCOMPtr<nsISupports> tempISupports;
nsCOMPtr<nsISimpleEnumerator> iterator;
RandomStream *randomStream;
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char *metaData;
PRUint32 testNum;
PRBool match;
PRInt32 recID;
int numRecords = 0;
// Iterate over all records in the cache
rv = cache->NewCacheEntryIterator(getter_AddRefs(iterator));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create new cache entry iterator");
PRBool notDone;
while (1) {
// Done iterating ?
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
// Get next record in iteration
rv = iterator->GetNext(getter_AddRefs(tempISupports));
NS_ASSERTION(NS_SUCCEEDED(rv), "iterator bustage");
record = do_QueryInterface(tempISupports);
numRecords++;
// Get record ID
rv = record->GetRecordID(&recID);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
testNum = mapRecordIdToTestNum(recID);
NS_ASSERTION(testNum != -1, "Corrupted Record ID ?");
// Erase mapping from table, so that duplicate enumerations are detected
recordID[testNum] = -1;
// Make sure stream matches test data
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
// Match against previously stored meta-data
rv = record->GetMetaData(&metaDataLength, &metaData);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
match = randomStream->Match(metaData, metaDataLength);
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
nsAllocator::Free(metaData);
delete randomStream;
}
NS_ASSERTION(numRecords == NUM_CACHE_ENTRIES, "Iteration bug");
return NS_OK;
}
// Read the test data that was written in FillCache(), checking for
// corruption, truncation.
nsresult
TestRead(nsINetDataCache *cache)
{
nsresult rv;
PRBool inCache;
nsCOMPtr<nsINetDataCacheRecord> record;
RandomStream *randomStream;
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char *metaData, *storedCacheKey;
PRUint32 testNum, storedCacheKeyLength;
PRBool match;
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
// Ensure that entry is in the cache
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
// Match against previously stored meta-data
match = record->GetMetaData(&metaDataLength, &metaData);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
match = randomStream->Match(metaData, metaDataLength);
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
nsAllocator::Free(metaData);
// Test GetKey() method
rv = record->GetKey(&storedCacheKeyLength, &storedCacheKey);
NS_ASSERTION(NS_SUCCEEDED(rv) &&
(storedCacheKeyLength == sizeof cacheKey) &&
!memcmp(storedCacheKey, &cacheKey[0], sizeof cacheKey),
"nsINetDataCacheRecord::GetKey failed");
nsAllocator::Free(storedCacheKey);
PRUint32 expectedStreamLength = randomStream->Next() & 0xffff;
TestReadStream(record, randomStream, expectedStreamLength);
}
WaitForEvents();
// Compute rate in MB/s
double rate = gTotalBytesRead / PR_IntervalToMilliseconds(gTotalDuration);
rate *= NUM_CACHE_ENTRIES;
rate *= 1000;
rate /= (1024 * 1024);
printf("Read %d bytes at a rate of %5.1f MB per second \n",
gTotalBytesRead, rate);
return NS_OK;
}
// Repeatedly call SetStoredContentLength() on a cache entry and make
// read the stream's data to ensure that it's not corrupted by the effect
nsresult
TestTruncation(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
RandomStream *randomStream;
char cacheKey[CACHE_KEY_LENGTH];
randomStream = new RandomStream(0);
randomStream->Read(cacheKey, sizeof cacheKey);
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
randomStream->Skip(CACHE_METADATA_LENGTH);
PRUint32 initialStreamLength = randomStream->Next() & 0xffff;
delete randomStream;
PRUint32 i;
PRUint32 delta = initialStreamLength / 64;
for (i = initialStreamLength; i >= delta; i -= delta) {
PRUint32 expectedStreamLength = i;
// Do the truncation
record->SetStoredContentLength(expectedStreamLength);
randomStream = new RandomStream(0);
randomStream->Skip(CACHE_KEY_LENGTH + CACHE_METADATA_LENGTH + 1);
TestReadStream(record, randomStream, expectedStreamLength);
WaitForEvents();
}
return NS_OK;
}
// Write known data to random offsets in a single cache entry and test
// resulting stream for correctness.
nsresult
TestOffsetWrites(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIOutputStream> outStream;
char buf[512];
char cacheKey[CACHE_KEY_LENGTH];
RandomStream *randomStream;
randomStream = new RandomStream(0);
randomStream->Read(cacheKey, sizeof cacheKey);
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
nsCOMPtr<nsIFileSpec> file ;
record->GetFilename(getter_AddRefs(file)) ;
char* name ;
file->GetUnixStyleFilePath(&name) ;
printf(" file name is %s \n", name) ;
// Write buffer-fulls of data at random offsets into the cache entry.
// Data written is (offset % 0xff)
PRUint32 startingOffset;
PRUint32 streamLength = 0;
PRUint32 len = 0 ;
CounterStream *counterStream;
int i = 0;
for (i = 0; i < 257; i++) {
rv = record->NewChannel(0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
startingOffset = streamLength ? streamLength - (randomStream->Next() % sizeof buf): 0;
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
truncate(name, startingOffset) ;
counterStream = new CounterStream(startingOffset);
counterStream->Read(buf, sizeof buf);
nsresult status ;
nsCOMPtr<nsIRandomAccessStore> ras = do_QueryInterface(outStream, &status);
if (NS_FAILED(status)) {
// mState = END_WRITE;
return NS_ERROR_FAILURE;
}
PRIntn offset ;
ras->Tell(&offset) ;
// printf(" offset is %d \n", offset) ;
PRUint32 numWritten;
rv = outStream->Write(buf, sizeof buf, &numWritten);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
streamLength = startingOffset + sizeof buf;
rv = outStream->Close();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
delete counterStream;
record->GetStoredContentLength(&len) ;
if(len != streamLength)
printf(" offset = %d is wrong, filesize = %d\n", startingOffset, len) ;
}
/*
rv = record->NewChannel(0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
startingOffset = 208;
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
counterStream = new CounterStream(startingOffset);
counterStream->Read(buf, sizeof buf);
nsresult status ;
nsCOMPtr<nsIRandomAccessStore> ras = do_QueryInterface(outStream, &status);
if (NS_FAILED(status)) {
// mState = END_WRITE;
return NS_ERROR_FAILURE;
}
PRIntn offset = 0 ;
ras->Tell(&offset) ;
printf(" offset is %d \n", offset) ;
PRUint32 numWritten;
rv = outStream->Write(buf, sizeof buf, &numWritten);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
streamLength = startingOffset + sizeof buf;
rv = outStream->Close();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
delete counterStream;
record->GetStoredContentLength(&len) ;
if(len != streamLength)
printf(" offset = %d is wrong, filesize = %d\n", startingOffset, len) ;
*/
delete randomStream;
counterStream = new CounterStream(0);
TestReadStream(record, counterStream, streamLength);
WaitForEvents();
return NS_OK;
}
// Create entries in the network data cache, using random data for the
// key, the meta-data and the stored content data.
nsresult
FillCache(nsINetDataCache *cache)
{
nsresult rv;
PRBool inCache;
nsCOMPtr<nsINetDataCacheRecord> record;
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIOutputStream> outStream;
char buf[1000];
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char metaData[CACHE_METADATA_LENGTH];
PRUint32 testNum;
char *data;
RandomStream *randomStream;
PRIntervalTime startTime = PR_IntervalNow();
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
// No entry should be in cache until we add it
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(!inCache, "nsINetDataCache::Contains error");
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
// Test nsINetDataCacheRecord::GetRecordID()
rv = record->GetRecordID(&recordID[testNum]);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
// Test nsINetDataCache::GetNumEntries()
PRUint32 numEntries = (PRUint32)-1;
rv = cache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == testNum + 1, "GetNumEntries failure");
// Record meta-data should be initially empty
rv = record->GetMetaData(&metaDataLength, &data);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
if ((metaDataLength != 0) || (data != 0))
return NS_ERROR_FAILURE;
// Store random data as meta-data
randomStream->Read(metaData, sizeof metaData);
record->SetMetaData(sizeof metaData, metaData);
rv = record->NewChannel(0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = channel->OpenOutputStream(0, getter_AddRefs(outStream));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
PRUint32 beforeOccupancy;
rv = cache->GetStorageInUse(&beforeOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
int streamLength = randomStream->Next() & 0xffff;
int remaining = streamLength;
while (remaining) {
PRUint32 numWritten;
int amount = PR_MIN(sizeof buf, remaining);
randomStream->Read(buf, amount);
rv = outStream->Write(buf, amount, &numWritten);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(numWritten == (PRUint32)amount, "Write() bug?");
remaining -= amount;
}
outStream->Close();
PRUint32 afterOccupancy;
rv = cache->GetStorageInUse(&afterOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
PRUint32 streamLengthInKB = streamLength >> 10;
NS_ASSERTION((afterOccupancy - beforeOccupancy) >= streamLengthInKB,
"nsINetDataCache::GetStorageInUse() is busted");
// *Now* there should be an entry in the cache
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
delete randomStream;
}
PRIntervalTime endTime = PR_IntervalNow();
return NS_OK;
}
nsresult NS_AutoregisterComponents()
{
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
NULL /* default */);
return rv;
}
PRBool initPref ()
{
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefPtr, kPrefCID, &rv);
if (NS_FAILED(rv))
return false;
nsCOMPtr<nsIFileSpec> fileSpec;
rv = NS_NewFileSpec (getter_AddRefs(fileSpec));
if (NS_FAILED(rv))
return false;
nsCString defaultPrefFile = PR_GetEnv ("MOZILLA_FIVE_HOME");
if (defaultPrefFile.Length())
defaultPrefFile += "/";
else
defaultPrefFile = "./";
defaultPrefFile += "default_prefs.js";
fileSpec->SetUnixStyleFilePath (defaultPrefFile.GetBuffer());
PRBool exists = false;
fileSpec->Exists(&exists);
if (exists)
prefPtr->ReadUserPrefsFrom(fileSpec);
else
return false;
return true;
}
int
main(int argc, char* argv[])
{
initPref() ;
nsresult rv;
nsCOMPtr<nsINetDataCache> cache;
rv = NS_AutoregisterComponents();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
rv = nsComponentManager::CreateInstance(kDiskCacheCID, nsnull,
NS_GET_IID(nsINetDataCache),
getter_AddRefs(cache));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create memory cache factory");
InitQueue();
PRUnichar* description;
rv = cache->GetDescription(&description);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache description");
nsCAutoString descStr(description);
printf("Testing: %s\n", descStr.GetBuffer());
rv = cache->RemoveAll();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
PRUint32 startOccupancy;
rv = cache->GetStorageInUse(&startOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
PRUint32 numEntries = (PRUint32)-1;
rv = cache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
rv = FillCache(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't fill cache with random test data");
rv = TestRead(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't read random test data from cache");
rv = TestRecordID(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't index records using record ID");
rv = TestEnumeration(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully enumerate records");
rv = TestTruncation(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully truncate records");
rv = TestOffsetWrites(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully write to records using non-zero offsets");
rv = cache->RemoveAll();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
rv = cache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
PRUint32 endOccupancy;
rv = cache->GetStorageInUse(&endOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
NS_ASSERTION(startOccupancy == endOccupancy, "Cache occupancy not correctly computed ?");
return 0;
}

View File

@@ -0,0 +1,48 @@
# Generated automatically from Makefile.in by configure.
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
VPATH = @srcdir@
srcdir = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = nkcache
LIBRARY_NAME = nkmemcache_s
REQUIRES = nspr dbm
EXPORTS=nsMemCacheCID.h \
nsMemCache.h \
$(NULL)
CPPSRCS = \
nsMemCache.cpp \
nsMemCacheRecord.cpp \
nsMemCacheChannel.cpp \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a
# static lib.
override NO_SHARED_LIB=1
override NO_STATIC_LIB=
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,42 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = nkcache
LIBRARY_NAME = nkmemcache_s
CPP_OBJS = \
.\$(OBJDIR)\nsMemCache.obj \
.\$(OBJDIR)\nsMemCacheRecord.obj \
.\$(OBJDIR)\nsMemCacheChannel.obj \
$(NULL)
EXPORTS=nsMemCacheCID.h
include <$(DEPTH)\config\rules.mak>
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -rf $(OBJDIR)
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,334 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
/**
* nsMemCache is the implementation of an in-memory network-data
* cache, used to cache the responses to network retrieval commands.
* Each cache entry may contain both content, e.g. GIF image data, and
* associated metadata, e.g. HTTP headers. Each entry is indexed by
* two different keys: a record id number and an opaque key, which is
* created by the cache manager by combining the URI with a "secondary
* key", e.g. HTTP post data.
*/
#include "nsMemCache.h"
#include "nsMemCacheRecord.h"
#include "nsIGenericFactory.h"
#include "nsString.h"
#include "nsHashtable.h"
#include "nsHashtableEnumerator.h"
#include "nsEnumeratorUtils.h"
PRInt32 nsMemCache::gRecordSerialNumber = 0;
nsMemCache::nsMemCache()
: mNumEntries(0), mOccupancy(0), mEnabled(PR_TRUE),
mHashTable(0)
{
NS_INIT_REFCNT();
}
nsMemCache::~nsMemCache()
{
nsresult rv;
rv = RemoveAll();
NS_ASSERTION(NS_SUCCEEDED(rv) && (mNumEntries == 0),
"Failure to shut down memory cache. "
"Somewhere, someone is holding references to at least one cache record");
delete mHashTable;
}
nsresult
nsMemCache::Init()
{
mHashTable = new nsHashtable(256);
if (!mHashTable)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMPL_ISUPPORTS(nsMemCache, NS_GET_IID(nsINetDataCache))
NS_IMETHODIMP
nsMemCache::GetDescription(PRUnichar * *aDescription)
{
nsAutoString description("Memory Cache");
*aDescription = description.ToNewUnicode();
if (!*aDescription)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::Contains(const char *aKey, PRUint32 aKeyLength, PRBool *aFound)
{
nsOpaqueKey *opaqueKey = new nsOpaqueKey(aKey, aKeyLength);
if (!opaqueKey)
return NS_ERROR_OUT_OF_MEMORY;
*aFound = mHashTable->Exists(opaqueKey);
delete opaqueKey;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetCachedNetData(const char *aKey, PRUint32 aKeyLength,
nsINetDataCacheRecord* *aRecord)
{
nsresult rv;
nsMemCacheRecord* record = 0;
nsOpaqueKey *opaqueKey2 = 0;
nsOpaqueKey *opaqueKey3 = 0;
nsOpaqueKey *opaqueKey;
opaqueKey = new nsOpaqueKey(aKey, aKeyLength);
if (!opaqueKey)
goto out_of_memory;
record = (nsMemCacheRecord*)mHashTable->Get(opaqueKey);
delete opaqueKey;
// No existing cache database entry was found. Create a new one.
// This requires two mappings in the hash table:
// Record ID ==> record
// Opaque key ==> record
if (!record) {
record = new nsMemCacheRecord;
if (!record)
goto out_of_memory;
rv = record->Init(aKey, aKeyLength, ++gRecordSerialNumber, this);
if (NS_FAILED(rv)) goto out_of_memory;
// Index the record by opaque key
opaqueKey2 = new nsOpaqueKey(record->mKey, record->mKeyLength);
if (!opaqueKey2) goto out_of_memory;
mHashTable->Put(opaqueKey2, record);
// Index the record by it's record ID
char *recordIDbytes = NS_REINTERPRET_CAST(char *, &record->mRecordID);
opaqueKey3 = new nsOpaqueKey(recordIDbytes,
sizeof record->mRecordID);
if (!opaqueKey3) {
// Clean up the first record from the hash table
mHashTable->Remove(opaqueKey);
goto out_of_memory;
}
mHashTable->Put(opaqueKey3, record);
// The hash table holds on to the record
record->AddRef();
delete opaqueKey2;
delete opaqueKey3;
mNumEntries++;
}
record->AddRef();
*aRecord = record;
return NS_OK;
out_of_memory:
delete opaqueKey2;
delete opaqueKey3;
delete record;
return NS_ERROR_OUT_OF_MEMORY;
}
NS_IMETHODIMP
nsMemCache::GetCachedNetDataByID(PRInt32 RecordID,
nsINetDataCacheRecord* *aRecord)
{
nsOpaqueKey opaqueKey(NS_REINTERPRET_CAST(const char *, &RecordID),
sizeof RecordID);
*aRecord = (nsINetDataCacheRecord*)mHashTable->Get(&opaqueKey);
if (*aRecord) {
NS_ADDREF(*aRecord);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_METHOD
nsMemCache::Delete(nsMemCacheRecord* aRecord)
{
nsMemCacheRecord *removedRecord;
char *recordIDbytes = NS_REINTERPRET_CAST(char *, &aRecord->mRecordID);
nsOpaqueKey opaqueRecordIDKey(recordIDbytes,
sizeof aRecord->mRecordID);
removedRecord = (nsMemCacheRecord*)mHashTable->Remove(&opaqueRecordIDKey);
NS_ASSERTION(removedRecord == aRecord, "memory cache database inconsistent");
nsOpaqueKey opaqueKey(aRecord->mKey, aRecord->mKeyLength);
removedRecord = (nsMemCacheRecord*)mHashTable->Remove(&opaqueKey);
NS_ASSERTION(removedRecord == aRecord, "memory cache database inconsistent");
aRecord->Release();
mNumEntries--;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetEnabled(PRBool *aEnabled)
{
NS_ENSURE_ARG(aEnabled);
*aEnabled = mEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::SetEnabled(PRBool aEnabled)
{
mEnabled = aEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetFlags(PRUint32 *aFlags)
{
NS_ENSURE_ARG(aFlags);
*aFlags = MEMORY_CACHE;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetNumEntries(PRUint32 *aNumEntries)
{
NS_ENSURE_ARG(aNumEntries);
*aNumEntries = mNumEntries;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetMaxEntries(PRUint32 *aMaxEntries)
{
NS_ENSURE_ARG(aMaxEntries);
*aMaxEntries = MEM_CACHE_MAX_ENTRIES;
return NS_OK;
}
static NS_METHOD
HashEntryConverter(nsHashKey *aKey, void *aValue,
void *unused, nsISupports **retval)
{
nsMemCacheRecord *record;
nsOpaqueKey *opaqueKey;
record = (nsMemCacheRecord*)aValue;
opaqueKey = (nsOpaqueKey*)aKey;
// Hash table keys that index cache entries by their record ID
// shouldn't be enumerated.
if ((opaqueKey->GetKeyLength() == sizeof(PRInt32))) {
#ifdef DEBUG
PRInt32 recordID;
record->GetRecordID(&recordID);
NS_ASSERTION(*((PRInt32*)opaqueKey->GetKey()) == recordID,
"Key has incorrect key length");
#endif
return NS_ERROR_FAILURE;
}
NS_IF_ADDREF(record);
*retval = NS_STATIC_CAST(nsISupports*, record);
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::NewCacheEntryIterator(nsISimpleEnumerator* *aIterator)
{
nsCOMPtr<nsIEnumerator> iterator;
NS_ENSURE_ARG(aIterator);
NS_NewHashtableEnumerator(mHashTable, HashEntryConverter,
mHashTable, getter_AddRefs(iterator));
return NS_NewAdapterEnumerator(aIterator, iterator);
}
NS_IMETHODIMP
nsMemCache::GetNextCache(nsINetDataCache* *aNextCache)
{
NS_ENSURE_ARG(aNextCache);
*aNextCache = mNextCache;
NS_ADDREF(*aNextCache);
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::SetNextCache(nsINetDataCache* aNextCache)
{
mNextCache = aNextCache;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetStorageInUse(PRUint32 *aStorageInUse)
{
NS_ENSURE_ARG(aStorageInUse);
// Convert from bytes to KB
*aStorageInUse = (mOccupancy >> 10);
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::RemoveAll(void)
{
PRBool failed;
nsCOMPtr<nsISimpleEnumerator> iterator;
nsCOMPtr<nsISupports> recordSupports;
nsCOMPtr<nsINetDataCacheRecord> record;
nsresult rv;
failed = PR_FALSE;
rv = NewCacheEntryIterator(getter_AddRefs(iterator));
if (NS_FAILED(rv))
return rv;
PRBool notDone;
while (1) {
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
iterator->GetNext(getter_AddRefs(recordSupports));
record = do_QueryInterface(recordSupports);
recordSupports = 0;
PRUint32 bytesUsed;
record->GetStoredContentLength(&bytesUsed);
rv = record->Delete();
if (NS_FAILED(rv)) {
failed = PR_TRUE;
continue;
}
mOccupancy -= bytesUsed;
}
if (failed)
return NS_ERROR_FAILURE;
return NS_OK;
}

View File

@@ -0,0 +1,83 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
/**
* nsMemCache is the implementation of an in-memory network-data
* cache, used to cache the responses to network retrieval commands.
* Each cache entry may contain both content, e.g. GIF image data, and
* associated metadata, e.g. HTTP headers. Each entry is indexed by
* two different keys: a record id number and an opaque key, which is
* created by the cache manager by combining the URI with a "secondary
* key", e.g. HTTP post data.
*/
#ifndef _nsMemCache_h_
#define _nsMemCache_h_
#include "nsINetDataCache.h"
// Maximum number of URIs that may be resident in the cache
#define MEM_CACHE_MAX_ENTRIES 1000
#define MEM_CACHE_SEGMENT_SIZE (1 << 12)
#define MEM_CACHE_MAX_ENTRY_SIZE (1 << 20)
class nsHashtable;
class nsMemCacheRecord;
class nsMemCache : public nsINetDataCache
{
public:
nsMemCache();
virtual ~nsMemCache();
nsresult Init();
// nsISupports methods
NS_DECL_ISUPPORTS
// nsINetDataCache methods
NS_DECL_NSINETDATACACHE
// Factory
static NS_METHOD nsMemCacheConstructor(nsISupports *aOuter, REFNSIID aIID,
void **aResult);
protected:
PRUint32 mNumEntries;
PRUint32 mOccupancy; // Memory used, in bytes
PRBool mEnabled; // If false, bypass mem cache
nsINetDataCache* mNextCache;
// Mapping from either opaque key or record ID to nsMemCacheRecord
nsHashtable* mHashTable;
// Used to assign record ID's
static PRInt32 gRecordSerialNumber;
NS_METHOD Delete(nsMemCacheRecord* aRecord);
friend class nsMemCacheRecord;
friend class nsMemCacheChannel;
};
#endif // _nsMemCache_h_

View File

@@ -0,0 +1,36 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
// XPCOM Class ID for the network data in-memory cache
#ifndef nsMEMCACHECID_h__
#define nsMEMCACHECID_h__
// {e4710560-7de2-11d3-90cb-0040056a906e}
#define NS_MEM_CACHE_FACTORY_CID \
{ \
0xe4710560, \
0x7de2, \
0x11d3, \
{0x90, 0xcb, 0x00, 0x40, 0x05, 0x6a, 0x90, 0x6e} \
}
#endif // nsMEMCACHECID_h__

View File

@@ -0,0 +1,462 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
#include "nsMemCache.h"
#include "nsMemCacheChannel.h"
#include "nsIStreamListener.h"
#include "nsIChannel.h"
#include "nsIStorageStream.h"
#include "nsIOutputStream.h"
#include "nsIServiceManager.h"
#include "nsIEventQueueService.h"
#include "nsNetUtil.h"
#include "nsILoadGroup.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
NS_IMPL_ISUPPORTS(nsMemCacheChannel, NS_GET_IID(nsIChannel))
void
nsMemCacheChannel::NotifyStorageInUse(PRInt32 aBytesUsed)
{
mRecord->mCache->mOccupancy += aBytesUsed;
}
/**
* This class acts as an adaptor around a synchronous input stream to add async
* read capabilities. It adds methods for initiating, suspending, resuming and
* cancelling async reads.
*/
class AsyncReadStreamAdaptor : public nsIInputStream {
public:
AsyncReadStreamAdaptor(nsMemCacheChannel* aChannel, nsIInputStream *aSyncStream):
mSyncStream(aSyncStream), mDataAvailCursor(0),
mRemaining(0), mAvailable(0), mChannel(aChannel), mAborted(PR_FALSE), mSuspended(PR_FALSE)
{
NS_INIT_REFCNT();
NS_ADDREF(mChannel);
}
virtual ~AsyncReadStreamAdaptor() {
mChannel->mAsyncReadStream = 0;
NS_RELEASE(mChannel);
}
NS_DECL_ISUPPORTS
nsresult
IsPending(PRBool* aIsPending) {
*aIsPending = (mRemaining != 0) && !mAborted;
return NS_OK;
}
nsresult
Cancel(void) {
mAborted = PR_TRUE;
return mStreamListener->OnStopRequest(mChannel, mContext, NS_BINDING_ABORTED, nsnull);
}
nsresult
Suspend(void) { mSuspended = PR_TRUE; return NS_OK; }
nsresult
Resume(void) {
if (!mSuspended)
return NS_ERROR_FAILURE;
mSuspended = PR_FALSE;
return NextListenerEvent();
}
NS_IMETHOD
Available(PRUint32 *aNumBytes) { return mAvailable; }
NS_IMETHOD
Read(char* aBuf, PRUint32 aCount, PRUint32 *aBytesRead) {
if (mAborted)
return NS_ERROR_ABORT;
*aBytesRead = 0;
aCount = PR_MIN(aCount, mAvailable);
nsresult rv = mSyncStream->Read(aBuf, aCount, aBytesRead);
mAvailable -= *aBytesRead;
if (NS_FAILED(rv) && (rv != NS_BASE_STREAM_WOULD_BLOCK)) {
Fail();
return rv;
}
if (!mSuspended && !mAvailable) {
rv = NextListenerEvent();
if (NS_FAILED(rv)) {
Fail();
return rv;
}
}
return NS_OK;
}
NS_IMETHOD
Close() {
nsresult rv = mSyncStream->Close();
mSyncStream = 0;
mContext = 0;
mStreamListener = 0;
return rv;
}
nsresult
AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
nsISupports* aContext, nsIStreamListener* aListener) {
nsresult rv;
nsIEventQueue *eventQ;
mContext = aContext;
mStreamListener = aListener;
mRemaining = aReadCount;
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueService, &rv);
if (NS_FAILED(rv)) return rv;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ);
if (NS_FAILED(rv)) return rv;
rv = NS_NewAsyncStreamListener(aListener, eventQ,
getter_AddRefs(mStreamListener));
NS_RELEASE(eventQ);
if (NS_FAILED(rv)) return rv;
rv = mStreamListener->OnStartRequest(mChannel, aContext);
if (NS_FAILED(rv)) return rv;
return NextListenerEvent();
}
protected:
nsresult
Fail(void) {
mAborted = PR_TRUE;
return mStreamListener->OnStopRequest(mChannel, mContext, NS_BINDING_FAILED, nsnull);
}
nsresult
NextListenerEvent() {
PRUint32 available;
nsresult rv = mSyncStream->Available(&available);
if (NS_FAILED(rv)) return rv;
available -= mAvailable;
available = PR_MIN(available, mRemaining);
if (available) {
PRUint32 size = PR_MIN(available, MEM_CACHE_SEGMENT_SIZE);
rv = mStreamListener->OnDataAvailable(mChannel, mContext, this,
mDataAvailCursor, size);
mDataAvailCursor += size;
mRemaining -= size;
mAvailable += size;
return rv;
} else {
rv = mStreamListener->OnStopRequest(mChannel, mContext, NS_OK, nsnull);
AsyncReadStreamAdaptor* thisAlias = this;
NS_RELEASE(thisAlias);
return rv;
}
}
private:
nsCOMPtr<nsISupports> mContext; // Opaque context passed to AsyncRead()
nsCOMPtr<nsIStreamListener> mStreamListener; // Stream listener that has been proxied
nsCOMPtr<nsIInputStream> mSyncStream; // Underlying synchronous stream that is
// being converted to an async stream
PRUint32 mDataAvailCursor;
PRUint32 mRemaining; // Size of AsyncRead request less bytes for
// consumer OnDataAvailable's that were fired
PRUint32 mAvailable; // Number of bytes for which OnDataAvailable fired
nsMemCacheChannel* mChannel; // Associated memory cache channel, strong link
// but can not use nsCOMPtr
PRBool mAborted; // Abort() has been called
PRBool mSuspended; // Suspend() has been called
};
NS_IMPL_ISUPPORTS(AsyncReadStreamAdaptor, NS_GET_IID(nsIInputStream))
// The only purpose of this output stream wrapper is to adjust the cache's
// overall occupancy as new data flows into the cache entry.
class MemCacheWriteStreamWrapper : public nsIOutputStream {
public:
MemCacheWriteStreamWrapper(nsMemCacheChannel* aChannel, nsIOutputStream *aBaseStream):
mBaseStream(aBaseStream), mChannel(aChannel)
{
NS_INIT_REFCNT();
NS_ADDREF(mChannel);
}
virtual ~MemCacheWriteStreamWrapper() { NS_RELEASE(mChannel); };
static nsresult
Create(nsMemCacheChannel* aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* *aWrapper) {
MemCacheWriteStreamWrapper *wrapper =
new MemCacheWriteStreamWrapper(aChannel, aBaseStream);
if (!wrapper) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(wrapper);
*aWrapper = wrapper;
return NS_OK;
}
NS_DECL_ISUPPORTS
NS_IMETHOD
Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritten) {
*aNumWritten = 0;
nsresult rv = mBaseStream->Write(aBuffer, aCount, aNumWritten);
mChannel->NotifyStorageInUse(*aNumWritten);
return rv;
}
NS_IMETHOD
Flush() { return mBaseStream->Flush(); }
NS_IMETHOD
Close() { return mBaseStream->Close(); }
private:
nsCOMPtr<nsIOutputStream> mBaseStream;
nsMemCacheChannel* mChannel;
};
NS_IMPL_ISUPPORTS(MemCacheWriteStreamWrapper, NS_GET_IID(nsIOutputStream))
nsMemCacheChannel::nsMemCacheChannel(nsMemCacheRecord *aRecord, nsILoadGroup *aLoadGroup)
: mRecord(aRecord)
{
NS_INIT_REFCNT();
mRecord->mNumChannels++;
}
nsMemCacheChannel::~nsMemCacheChannel()
{
mRecord->mNumChannels--;
}
NS_IMETHODIMP
nsMemCacheChannel::IsPending(PRBool* aIsPending)
{
*aIsPending = PR_FALSE;
if (!mAsyncReadStream)
return NS_OK;
return mAsyncReadStream->IsPending(aIsPending);
}
NS_IMETHODIMP
nsMemCacheChannel::Cancel(void)
{
if (!mAsyncReadStream)
return NS_ERROR_FAILURE;
return mAsyncReadStream->Cancel();
}
NS_IMETHODIMP
nsMemCacheChannel::Suspend(void)
{
if (!mAsyncReadStream)
return NS_ERROR_FAILURE;
return mAsyncReadStream->Suspend();
}
NS_IMETHODIMP
nsMemCacheChannel::Resume(void)
{
if (!mAsyncReadStream)
return NS_ERROR_FAILURE;
return mAsyncReadStream->Resume();
}
NS_IMETHODIMP
nsMemCacheChannel::GetOriginalURI(nsIURI * *aURI)
{
// Not required
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetURI(nsIURI * *aURI)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
nsIInputStream* *aResult)
{
nsresult rv;
NS_ENSURE_ARG(aResult);
if (mInputStream)
return NS_ERROR_NOT_AVAILABLE;
rv = mRecord->mStorageStream->NewInputStream(aStartPosition, getter_AddRefs(mInputStream));
*aResult = mInputStream;
NS_ADDREF(*aResult);
return rv;
}
NS_IMETHODIMP
nsMemCacheChannel::OpenOutputStream(PRUint32 startPosition, nsIOutputStream* *aResult)
{
nsresult rv;
NS_ENSURE_ARG(aResult);
nsCOMPtr<nsIOutputStream> outputStream;
PRUint32 oldLength;
mRecord->mStorageStream->GetLength(&oldLength);
rv = mRecord->mStorageStream->GetOutputStream(startPosition, getter_AddRefs(outputStream));
if (NS_FAILED(rv)) return rv;
if (startPosition < oldLength)
NotifyStorageInUse(startPosition - oldLength);
return MemCacheWriteStreamWrapper::Create(this, outputStream, aResult);
}
NS_IMETHODIMP
nsMemCacheChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports *ctxt)
{
// Not required
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
nsISupports *aContext, nsIStreamListener *aListener)
{
nsCOMPtr<nsIInputStream> inputStream;
nsresult rv = OpenInputStream(aStartPosition, aReadCount, getter_AddRefs(inputStream));
if (NS_FAILED(rv)) return rv;
AsyncReadStreamAdaptor *asyncReadStreamAdaptor;
asyncReadStreamAdaptor = new AsyncReadStreamAdaptor(this, inputStream);
if (!asyncReadStreamAdaptor)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(asyncReadStreamAdaptor);
mAsyncReadStream = asyncReadStreamAdaptor;
rv = asyncReadStreamAdaptor->AsyncRead(aStartPosition, aReadCount, aContext, aListener);
if (NS_FAILED(rv))
delete asyncReadStreamAdaptor;
return rv;
}
NS_IMETHODIMP
nsMemCacheChannel::AsyncWrite(nsIInputStream *fromStream, PRUint32 startPosition,
PRInt32 writeCount, nsISupports *ctxt,
nsIStreamObserver *observer)
{
// Not required to be implemented
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetContentType(char* *aContentType)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetContentLength(PRInt32 *aContentLength)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetOwner(nsISupports* *aOwner)
{
*aOwner = mOwner.get();
NS_IF_ADDREF(*aOwner);
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheChannel::SetOwner(nsISupports* aOwner)
{
// Not required to be implemented, since it is implemented by cache manager
mOwner = aOwner;
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@@ -0,0 +1,61 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
#ifndef _nsMemCacheChannel_h_
#define _nsMemCacheChannel_h_
#include "nsMemCacheRecord.h"
#include "nsIChannel.h"
#include "nsIInputStream.h"
#include "nsCOMPtr.h"
class AsyncReadStreamAdaptor;
class nsMemCacheChannel : public nsIChannel
{
public:
// Constructors and Destructor
nsMemCacheChannel(nsMemCacheRecord *aRecord, nsILoadGroup *aLoadGroup);
virtual ~nsMemCacheChannel();
// Declare nsISupports methods
NS_DECL_ISUPPORTS
// Declare nsIRequest methods
NS_DECL_NSIREQUEST
// Declare nsIChannel methods
NS_DECL_NSICHANNEL
protected:
void NotifyStorageInUse(PRInt32 aBytesUsed);
nsCOMPtr<nsMemCacheRecord> mRecord;
nsCOMPtr<nsIInputStream> mInputStream;
nsCOMPtr<nsISupports> mOwner;
AsyncReadStreamAdaptor* mAsyncReadStream; // non-owning pointer
friend class MemCacheWriteStreamWrapper;
friend class AsyncReadStreamAdaptor;
};
#endif // _nsMemCacheChannel_h_

View File

@@ -0,0 +1,164 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
#include "nsMemCache.h"
#include "nsMemCacheRecord.h"
#include "nsMemCacheChannel.h"
#include "nsIAllocator.h"
#include "nsStorageStream.h"
static NS_DEFINE_IID(kINetDataCacheRecord, NS_INETDATACACHERECORD_IID);
nsMemCacheRecord::nsMemCacheRecord()
: mKey(0), mKeyLength(0), mMetaData(0), mMetaDataLength(0), mNumChannels(0)
{
NS_INIT_REFCNT();
}
nsMemCacheRecord::~nsMemCacheRecord()
{
if (mMetaData)
delete[] mMetaData;
if (mKey)
delete[] mKey;
}
NS_IMPL_ISUPPORTS(nsMemCacheRecord, NS_GET_IID(nsINetDataCacheRecord))
NS_IMETHODIMP
nsMemCacheRecord::GetKey(PRUint32 *aLength, char **aResult)
{
NS_ENSURE_ARG(aResult);
*aResult = (char *)nsAllocator::Alloc(mKeyLength);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
memcpy(*aResult, mKey, mKeyLength);
*aLength = mKeyLength;
return NS_OK;
}
nsresult
nsMemCacheRecord::Init(const char *aKey, PRUint32 aKeyLength,
PRUint32 aRecordID, nsMemCache *aCache)
{
nsresult rv;
NS_ASSERTION(!mKey, "Memory cache record key set multiple times");
rv = NS_NewStorageStream(MEM_CACHE_SEGMENT_SIZE, MEM_CACHE_MAX_ENTRY_SIZE,
getter_AddRefs(mStorageStream));
if (NS_FAILED(rv)) return rv;
mKey = new char[aKeyLength];
if (!mKey)
return NS_ERROR_OUT_OF_MEMORY;
memcpy(mKey, aKey, aKeyLength);
mKeyLength = aKeyLength;
mRecordID = aRecordID;
mCache = aCache;
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheRecord::GetRecordID(PRInt32 *aRecordID)
{
NS_ENSURE_ARG(aRecordID);
*aRecordID = mRecordID;
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheRecord::GetMetaData(PRUint32 *aLength, char **aResult)
{
NS_ENSURE_ARG(aResult);
*aResult = 0;
if (mMetaDataLength) {
*aResult = (char*)nsAllocator::Alloc(mMetaDataLength);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
memcpy(*aResult, mMetaData, mMetaDataLength);
}
*aLength = mMetaDataLength;
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheRecord::SetMetaData(PRUint32 aLength, const char *aData)
{
if (mMetaData)
delete[] mMetaData;
mMetaData = new char[aLength];
if (!mMetaData)
return NS_ERROR_OUT_OF_MEMORY;
memcpy(mMetaData, aData, aLength);
mMetaDataLength = aLength;
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheRecord::GetStoredContentLength(PRUint32 *aStoredContentLength)
{
NS_ENSURE_ARG(aStoredContentLength);
return mStorageStream->GetLength(aStoredContentLength);
}
NS_IMETHODIMP
nsMemCacheRecord::SetStoredContentLength(PRUint32 aStoredContentLength)
{
PRUint32 before, after;
mStorageStream->GetLength(&before);
nsresult rv = mStorageStream->SetLength(aStoredContentLength);
if (NS_FAILED(rv)) return rv;
mStorageStream->GetLength(&after);
mCache->mOccupancy -= (before - after);
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheRecord::Delete(void)
{
if (mNumChannels)
return NS_ERROR_NOT_AVAILABLE;
return mCache->Delete(this);
}
NS_IMETHODIMP
nsMemCacheRecord::GetFilename(nsIFileSpec* *aFilename)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheRecord::NewChannel(nsILoadGroup *aLoadGroup, nsIChannel* *aResult)
{
NS_ENSURE_ARG(aResult);
nsMemCacheChannel* channel = new nsMemCacheChannel(this, aLoadGroup);
if (!channel)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(channel);
*aResult = NS_STATIC_CAST(nsIChannel*, channel);
return NS_OK;
}

View File

@@ -0,0 +1,65 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
#ifndef _nsMemCacheRecord_h_
#define _nsMemCacheRecord_h_
#include "nsINetDataCacheRecord.h"
#include "nsIStorageStream.h"
#include "nsCOMPtr.h"
class nsMemCache;
class nsMemCacheRecord : public nsINetDataCacheRecord
{
public:
// Declare interface methods
NS_DECL_ISUPPORTS
NS_DECL_NSINETDATACACHERECORD
protected:
// Constructors and Destructor
nsMemCacheRecord();
virtual ~nsMemCacheRecord();
nsresult Init(const char *aKey, PRUint32 aKeyLength,
PRUint32 aRecordID, nsMemCache *aCache);
char* mKey; // opaque database key for this record
PRUint32 mKeyLength; // length, in bytes, of mKey
PRInt32 mRecordID; // An alternate key for this record
char* mMetaData; // opaque URI metadata
PRUint32 mMetaDataLength; // length, in bytes, of mMetaData
nsMemCache* mCache; // weak pointer to the cache database
// that this record inhabits
nsCOMPtr<nsIStorageStream> mStorageStream;
PRUint32 mNumChannels; // Count un-Release'ed nsIChannels
friend class nsMemCache;
friend class nsMemCacheChannel;
};
#endif // _nsMemCacheRecord_h_

55
mozilla/netwerk/cache/mgr/Makefile.in vendored Normal file
View File

@@ -0,0 +1,55 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = nkcache
LIBRARY_NAME = nkcachemgr_s
REQUIRES = nspr
EXPORTS = \
nsCacheManager.h \
$(NULL)
CPPSRCS = \
nsCacheManager.cpp \
nsCachedNetData.cpp \
nsReplacementPolicy.cpp \
nsCacheEntryChannel.cpp \
$(NULL)
LOCAL_INCLUDES = -I$(srcdir)/../public -I$(srcdir)/../include
EXTRA_LIBS = $(NSPR_LIBS)
# we don't want the shared lib, but we want to force the creation of a
# static lib.
override NO_SHARED_LIB=1
override NO_STATIC_LIB=
include $(topsrcdir)/config/rules.mk

45
mozilla/netwerk/cache/mgr/Makefile.win vendored Executable file
View File

@@ -0,0 +1,45 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = nkcache
LIBRARY_NAME = nkcachemgr_s
CPP_OBJS = \
.\$(OBJDIR)\nsCacheManager.obj \
.\$(OBJDIR)\nsCachedNetData.obj \
.\$(OBJDIR)\nsReplacementPolicy.obj \
.\$(OBJDIR)\nsCacheEntryChannel.obj \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -rf $(OBJDIR)
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,261 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#include "nsCacheManager.h"
#include "nsCacheEntryChannel.h"
#include "nsIOutputStream.h"
#include "nsIIOService.h"
#include "nsIServiceManager.h"
#include "nsIStreamListener.h"
nsCacheEntryChannel::nsCacheEntryChannel(nsCachedNetData* aCacheEntry, nsIChannel* aChannel,
nsILoadGroup* aLoadGroup):
nsChannelProxy(aChannel), mCacheEntry(aCacheEntry), mLoadGroup(aLoadGroup), mLoadAttributes(0)
{
NS_ASSERTION(aCacheEntry->mChannelCount < 0xFF, "Overflowed channel counter");
mCacheEntry->mChannelCount++;
NS_INIT_REFCNT();
}
nsCacheEntryChannel::~nsCacheEntryChannel()
{
mCacheEntry->mChannelCount--;
}
NS_IMPL_ISUPPORTS3(nsCacheEntryChannel, nsISupports, nsIChannel, nsIRequest)
// A proxy for nsIOutputStream
class CacheOutputStream : public nsIOutputStream {
public:
CacheOutputStream(nsIOutputStream *aOutputStream, nsCachedNetData *aCacheEntry):
mOutputStream(aOutputStream), mCacheEntry(aCacheEntry), mStartTime(PR_Now())
{ NS_INIT_REFCNT(); }
virtual ~CacheOutputStream() {
mCacheEntry->NoteDownloadTime(mStartTime, PR_Now());
mCacheEntry->ClearFlag(nsCachedNetData::UPDATE_IN_PROGRESS);
}
NS_DECL_ISUPPORTS
NS_IMETHOD Close() {
return mOutputStream->Close();
}
NS_IMETHOD Flush() { return mOutputStream->Flush(); }
NS_IMETHOD
Write(const char *aBuf, PRUint32 aCount, PRUint32 *aActualBytes) {
nsresult rv;
*aActualBytes = 0;
rv = mOutputStream->Write(aBuf, aCount, aActualBytes);
mCacheEntry->mLogicalLength += *aActualBytes;
if (NS_FAILED(rv)) return rv;
nsCacheManager::LimitCacheSize();
return rv;
}
protected:
nsCOMPtr<nsIOutputStream> mOutputStream;
nsCOMPtr<nsCachedNetData> mCacheEntry;
// Time at which stream was opened
PRTime mStartTime;
};
NS_IMPL_ISUPPORTS(CacheOutputStream, NS_GET_IID(nsIOutputStream))
NS_IMETHODIMP
nsCacheEntryChannel::OpenOutputStream(PRUint32 aStartPosition, nsIOutputStream* *aOutputStream)
{
nsresult rv;
nsCOMPtr<nsIOutputStream> baseOutputStream;
rv = mChannel->OpenOutputStream(aStartPosition, getter_AddRefs(baseOutputStream));
if (NS_FAILED(rv)) return rv;
mCacheEntry->NoteUpdate();
mCacheEntry->NoteAccess();
mCacheEntry->mLogicalLength = aStartPosition;
*aOutputStream = new CacheOutputStream(baseOutputStream, mCacheEntry);
if (!*aOutputStream)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aOutputStream);
return NS_OK;
}
NS_IMETHODIMP
nsCacheEntryChannel::OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
nsIInputStream* *aInputStream)
{
mCacheEntry->NoteAccess();
return mChannel->OpenInputStream(aStartPosition, aReadCount, aInputStream);
}
class CacheManagerStreamListener: public nsIStreamListener {
public:
CacheManagerStreamListener(nsIStreamListener *aListener,
nsILoadGroup *aLoadGroup, nsIChannel *aChannel):
mListener(aListener), mLoadGroup(aLoadGroup), mChannel(aChannel)
{ NS_INIT_REFCNT(); }
virtual ~CacheManagerStreamListener() {}
private:
NS_DECL_ISUPPORTS
NS_IMETHOD
OnDataAvailable(nsIChannel *channel, nsISupports *aContext,
nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count) {
return mListener->OnDataAvailable(mChannel, aContext, inStr, sourceOffset, count);
}
NS_IMETHOD
OnStartRequest(nsIChannel *channel, nsISupports *aContext) {
if (mLoadGroup)
mLoadGroup->AddChannel(mChannel, aContext);
return mListener->OnStartRequest(mChannel, aContext);
}
NS_IMETHOD
OnStopRequest(nsIChannel *channel, nsISupports *aContext,
nsresult status, const PRUnichar *errorMsg) {
nsresult rv;
rv = mListener->OnStopRequest(mChannel, aContext, status, errorMsg);
if (mLoadGroup)
mLoadGroup->RemoveChannel(mChannel, aContext, status, errorMsg);
return rv;
}
private:
nsCOMPtr<nsIStreamListener> mListener;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCOMPtr<nsIChannel> mChannel;
};
NS_IMPL_ISUPPORTS2(CacheManagerStreamListener, nsIStreamListener, nsIStreamObserver)
NS_IMETHODIMP
nsCacheEntryChannel::AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
nsISupports *aContext, nsIStreamListener *aListener)
{
nsresult rv;
mCacheEntry->NoteAccess();
nsCOMPtr<nsIStreamListener> headListener;
if (mLoadGroup) {
mLoadGroup->GetDefaultLoadAttributes(&mLoadAttributes);
// Create a load group "proxy" listener...
nsCOMPtr<nsILoadGroupListenerFactory> factory;
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
if (NS_SUCCEEDED(rv) && factory) {
rv = factory->CreateLoadGroupListener(aListener,
getter_AddRefs(headListener));
if (NS_FAILED(rv)) return rv;
}
} else {
headListener = aListener;
}
CacheManagerStreamListener* cacheManagerStreamListener;
nsIChannel *channelForListener;
channelForListener = mProxyChannel ? mProxyChannel.get() : NS_STATIC_CAST(nsIChannel*, this);
cacheManagerStreamListener =
new CacheManagerStreamListener(headListener, mLoadGroup, channelForListener);
if (!cacheManagerStreamListener) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(cacheManagerStreamListener);
rv = mChannel->AsyncRead(aStartPosition, aReadCount, aContext,
cacheManagerStreamListener);
NS_RELEASE(cacheManagerStreamListener);
return rv;
}
// No async writes allowed to the cache yet
NS_IMETHODIMP
nsCacheEntryChannel::AsyncWrite(nsIInputStream *aFromStream, PRUint32 aStartPosition,
PRInt32 aWriteCount, nsISupports *aContext,
nsIStreamObserver *aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheEntryChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
*aLoadGroup = mLoadGroup;
return NS_OK;
}
NS_IMETHODIMP
nsCacheEntryChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
{
*aLoadAttributes = mLoadAttributes;
return NS_OK;
}
NS_IMETHODIMP
nsCacheEntryChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
{
mLoadAttributes = aLoadAttributes;
return NS_OK;
}
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
NS_IMETHODIMP
nsCacheEntryChannel::GetURI(nsIURI * *aURI)
{
char* spec;
nsresult rv;
rv = mCacheEntry->GetUriSpec(&spec);
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = serv->NewURI(spec, 0, aURI);
nsAllocator::Free(spec);
return rv;
}
NS_IMETHODIMP
nsCacheEntryChannel::GetOriginalURI(nsIURI * *aURI)
{
// FIXME - should return original URI passed into NewChannel() ?
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@@ -0,0 +1,82 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#ifndef _nsCacheEntryChannel_h_
#define _nsCacheEntryChannel_h_
#include "nsCOMPtr.h"
#include "nsIChannel.h"
#include "nsCachedNetData.h"
#include "nsILoadGroup.h"
class nsIStreamListener;
// A proxy for an nsIChannel, useful when only a few nsIChannel
// methods must be overridden
class nsChannelProxy : public nsIChannel {
public:
NS_FORWARD_NSICHANNEL(mChannel->)
NS_FORWARD_NSIREQUEST(mChannel->)
protected:
nsChannelProxy(nsIChannel* aChannel):mChannel(aChannel) {};
virtual ~nsChannelProxy() {};
nsCOMPtr<nsIChannel> mChannel;
};
// Override several nsIChannel methods so that they interact with the cache manager
class nsCacheEntryChannel : public nsChannelProxy {
public:
NS_DECL_ISUPPORTS
NS_IMETHOD OpenOutputStream(PRUint32 aStartPosition, nsIOutputStream* *aOutputStream);
NS_IMETHOD OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
nsIInputStream* *aInputStream);
NS_IMETHOD AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
nsISupports *aContext, nsIStreamListener *aListener);
NS_IMETHOD AsyncWrite(nsIInputStream *aFromStream, PRUint32 aStartPosition,
PRInt32 aWriteCount, nsISupports *aContext,
nsIStreamObserver *aObserver);
NS_IMETHOD GetLoadAttributes(nsLoadFlags *aLoadAttributes);
NS_IMETHOD SetLoadAttributes(nsLoadFlags aLoadAttributes);
NS_IMETHOD GetLoadGroup(nsILoadGroup* *aLoadGroup);
NS_IMETHOD GetURI(nsIURI * *aURI);
NS_IMETHOD GetOriginalURI(nsIURI * *aURI);
protected:
nsCacheEntryChannel(nsCachedNetData* aCacheEntry, nsIChannel* aChannel, nsILoadGroup* aLoadGroup);
virtual ~nsCacheEntryChannel();
friend class nsCachedNetData;
private:
nsCOMPtr<nsCachedNetData> mCacheEntry;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCOMPtr<nsIChannel> mProxyChannel;
nsLoadFlags mLoadAttributes;
};
#endif // _nsCacheEntryChannel_h_

View File

@@ -0,0 +1,497 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#include "nsINetDataCache.h"
#include "nsCacheManager.h"
#include "nsCachedNetData.h"
#include "nsReplacementPolicy.h"
#include "nsString.h"
#include "nsIURI.h"
#include "nsHashtable.h"
#include "nsIComponentManager.h"
#include "nsINetDataDiskCache.h"
// Limit the number of entries in the cache to conserve memory space
// in the nsReplacementPolicy code
#define MAX_MEM_CACHE_ENTRIES 800
#define MAX_DISK_CACHE_ENTRIES 3200
// Cache capacities in MB, overridable via APIs
#define DEFAULT_MEMORY_CACHE_CAPACITY 1024
#define DEFAULT_DISK_CACHE_CAPACITY 10000
#define CACHE_HIGH_WATER_MARK(capacity) ((PRUint32)(0.98 * (capacity)))
#define CACHE_LOW_WATER_MARK(capacity) ((PRUint32)(0.97 * (capacity)))
nsCacheManager* gCacheManager = 0;
NS_IMPL_ISUPPORTS(nsCacheManager, NS_GET_IID(nsINetDataCacheManager))
nsCacheManager::nsCacheManager()
: mActiveCacheRecords(0),
mDiskCacheCapacity(DEFAULT_DISK_CACHE_CAPACITY),
mMemCacheCapacity(DEFAULT_MEMORY_CACHE_CAPACITY)
{
NS_ASSERTION(!gCacheManager, "Multiple cache managers created");
gCacheManager = this;
NS_INIT_REFCNT();
}
nsCacheManager::~nsCacheManager()
{
gCacheManager = 0;
delete mActiveCacheRecords;
delete mMemSpaceManager;
delete mDiskSpaceManager;
}
nsresult
nsCacheManager::Init()
{
nsresult rv;
mActiveCacheRecords = new nsHashtable(64);
if (!mActiveCacheRecords)
return NS_ERROR_OUT_OF_MEMORY;
// Instantiate the memory cache component
rv = nsComponentManager::CreateInstance(NS_NETWORK_MEMORY_CACHE_PROGID,
nsnull,
NS_GET_IID(nsINetDataCache),
getter_AddRefs(mMemCache));
if (NS_FAILED(rv))
return rv;
rv = nsComponentManager::CreateInstance(NS_NETWORK_FLAT_CACHE_PROGID,
nsnull,
NS_GET_IID(nsINetDataCache),
getter_AddRefs(mFlatCache));
if (NS_FAILED(rv)) {
// For now, we don't require a flat cache module to be present
if (rv != NS_ERROR_FACTORY_NOT_REGISTERED)
return rv;
}
#ifdef FILE_CACHE_IS_READY
// Instantiate the file cache component
rv = nsComponentManager::CreateInstance(NS_NETWORK_FILE_CACHE_PROGID,
nsnull,
NS_GET_IID(nsINetDataCache),
getter_AddRefs(mFileCache));
if (NS_FAILED(rv)) {
NS_WARNING("No disk cache present");
}
#endif
// Set up linked list of caches in search order
mCacheSearchChain = mMemCache;
if (mFlatCache) {
mMemCache->SetNextCache(mFlatCache);
mFlatCache->SetNextCache(mFileCache);
} else {
mMemCache->SetNextCache(mFileCache);
}
// TODO - Load any extension caches here
// Initialize replacement policy for memory cache module
mMemSpaceManager = new nsReplacementPolicy;
if (!mMemSpaceManager)
return NS_ERROR_OUT_OF_MEMORY;
rv = mMemSpaceManager->Init(MAX_MEM_CACHE_ENTRIES);
if (NS_FAILED(rv)) return rv;
rv = mMemSpaceManager->AddCache(mMemCache);
// Initialize replacement policy for disk cache modules (file
// cache and flat cache)
mDiskSpaceManager = new nsReplacementPolicy;
if (!mDiskSpaceManager)
return NS_ERROR_OUT_OF_MEMORY;
rv = mDiskSpaceManager->Init(MAX_DISK_CACHE_ENTRIES);
if (NS_FAILED(rv)) return rv;
if (mFileCache) {
rv = mDiskSpaceManager->AddCache(mFileCache);
if (NS_FAILED(rv)) return rv;
}
if (mFlatCache) {
rv = mDiskSpaceManager->AddCache(mFlatCache);
if (NS_FAILED(rv)) return rv;
}
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::GetCachedNetData(const char *aUriSpec, const char *aSecondaryKey,
PRUint32 aSecondaryKeyLength,
PRUint32 aFlags, nsICachedNetData* *aResult)
{
nsCachedNetData *cachedData;
nsresult rv;
nsINetDataCache *cache;
nsReplacementPolicy *spaceManager;
if (aFlags & CACHE_AS_FILE) {
cache = mFileCache;
spaceManager = mDiskSpaceManager;
// Ensure that cache is initialized
if (mDiskCacheCapacity == (PRUint32)-1)
return NS_ERROR_NOT_AVAILABLE;
} else if ((aFlags & BYPASS_PERSISTENT_CACHE) ||
(!mFileCache && !mFlatCache) || !mDiskCacheCapacity) {
cache = mMemCache;
spaceManager = mMemSpaceManager;
} else {
cache = mFlatCache ? mFlatCache : mFileCache;
spaceManager = mDiskSpaceManager;
}
// Construct the cache key by appending the secondary key to the URI spec
nsCAutoString cacheKey(aUriSpec);
// Insert NUL at end of URI spec
cacheKey += '\0';
if (aSecondaryKey)
cacheKey.Append(aSecondaryKey, aSecondaryKeyLength);
nsStringKey key(cacheKey);
cachedData = (nsCachedNetData*)mActiveCacheRecords->Get(&key);
// There is no existing instance of nsCachedNetData for this URL.
// Make one from the corresponding record in the cache module.
if (cachedData) {
NS_ASSERTION(cache == cachedData->mCache,
"Cannot yet handle simultaneously active requests for the "
"same URL using different caches");
NS_ADDREF(cachedData);
} else {
rv = spaceManager->GetCachedNetData(cacheKey.GetBuffer(), cacheKey.Length(),
cache, &cachedData);
if (NS_FAILED(rv)) return rv;
mActiveCacheRecords->Put(&key, cachedData);
}
*aResult = cachedData;
return NS_OK;
}
// Remove this cache entry from the list of active ones
nsresult
nsCacheManager::NoteDormant(nsCachedNetData* aEntry)
{
nsresult rv;
PRUint32 keyLength;
char* key;
nsCOMPtr<nsINetDataCacheRecord> record;
nsCachedNetData* deletedEntry;
rv = aEntry->GetRecord(getter_AddRefs(record));
if (NS_FAILED(rv)) return rv;
rv = record->GetKey(&keyLength, &key);
if (NS_FAILED(rv)) return rv;
nsStringKey hashTableKey(nsCString(key, keyLength));
deletedEntry = (nsCachedNetData*)gCacheManager->mActiveCacheRecords->Remove(&hashTableKey);
// NS_ASSERTION(deletedEntry == aEntry, "Hash table inconsistency");
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::Contains(const char *aUriSpec, const char *aSecondaryKey,
PRUint32 aSecondaryKeyLength,
PRUint32 aFlags, PRBool *aResult)
{
nsINetDataCache *cache;
nsReplacementPolicy *spaceManager;
nsCachedNetData *cachedData;
if (aFlags & CACHE_AS_FILE) {
cache = mFileCache;
spaceManager = mDiskSpaceManager;
} else if ((aFlags & BYPASS_PERSISTENT_CACHE) ||
(!mFileCache && !mFlatCache) || !mDiskCacheCapacity) {
cache = mMemCache;
spaceManager = mMemSpaceManager;
} else {
cache = mFlatCache ? mFlatCache : mFileCache;
spaceManager = mDiskSpaceManager;
}
// Construct the cache key by appending the secondary key to the URI spec
nsCAutoString cacheKey(aUriSpec);
// Insert NUL between URI spec and secondary key
cacheKey += '\0';
cacheKey.Append(aSecondaryKey, aSecondaryKeyLength);
// Locate the record using (URI + secondary key)
nsStringKey key(cacheKey);
cachedData = (nsCachedNetData*)mActiveCacheRecords->Get(&key);
if (cachedData && (cache == cachedData->mCache)) {
*aResult = PR_TRUE;
return NS_OK;
} else {
// No active cache entry, see if there is a dormant one
return cache->Contains(cacheKey.GetBuffer(), cacheKey.Length(), aResult);
}
}
NS_IMETHODIMP
nsCacheManager::GetNumEntries(PRUint32 *aNumEntries)
{
nsresult rv;
nsCOMPtr<nsISimpleEnumerator> iterator;
nsCOMPtr<nsISupports> cacheSupports;
nsCOMPtr<nsINetDataCache> cache;
PRUint32 totalEntries = 0;
rv = NewCacheModuleIterator(getter_AddRefs(iterator));
if (NS_FAILED(rv)) return rv;
while (1) {
PRBool notDone;
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
iterator->GetNext(getter_AddRefs(cacheSupports));
cache = do_QueryInterface(cacheSupports);
PRUint32 numEntries;
rv = cache->GetNumEntries(&numEntries);
if (NS_FAILED(rv)) return rv;
totalEntries += numEntries;
}
*aNumEntries = totalEntries;
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::NewCacheEntryIterator(nsISimpleEnumerator* *aResult)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
class CacheEnumerator : public nsISimpleEnumerator
{
public:
CacheEnumerator(nsINetDataCache* aFirstCache):mCache(aFirstCache)
{ NS_INIT_REFCNT(); }
virtual ~CacheEnumerator() {};
NS_DECL_ISUPPORTS
NS_IMETHODIMP
HasMoreElements(PRBool* aMoreElements) {
*aMoreElements = (mCache != 0);
return NS_OK;
}
NS_IMETHODIMP
GetNext(nsISupports* *aSupports) {
*aSupports = mCache;
if (!mCache)
return NS_ERROR_FAILURE;
NS_ADDREF(*aSupports);
nsCOMPtr<nsINetDataCache> nextCache;
nsresult rv = mCache->GetNextCache(getter_AddRefs(nextCache));
mCache = nextCache;
return rv;
}
private:
nsCOMPtr<nsINetDataCache> mCache;
};
NS_IMPL_ISUPPORTS(CacheEnumerator, NS_GET_IID(nsISimpleEnumerator))
NS_IMETHODIMP
nsCacheManager::NewCacheModuleIterator(nsISimpleEnumerator* *aResult)
{
*aResult = new CacheEnumerator(mCacheSearchChain);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::RemoveAll(void)
{
nsresult rv, result;
nsCOMPtr<nsISimpleEnumerator> iterator;
nsCOMPtr<nsINetDataCache> cache;
nsCOMPtr<nsISupports> iSupports;
result = NS_OK;
rv = NewCacheModuleIterator(getter_AddRefs(iterator));
if (NS_FAILED(rv)) return rv;
while (1) {
PRBool notDone;
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
iterator->GetNext(getter_AddRefs(iSupports));
cache = do_QueryInterface(iSupports);
PRUint32 cacheFlags;
rv = cache->GetFlags(&cacheFlags);
if (NS_FAILED(rv)) return rv;
if ((cacheFlags & nsINetDataCache::READ_ONLY) == 0) {
rv = cache->RemoveAll();
if (NS_FAILED(rv))
result = rv;
}
}
return result;
}
nsresult
nsCacheManager::LimitMemCacheSize()
{
nsresult rv;
nsReplacementPolicy* spaceManager;
NS_ASSERTION(gCacheManager, "No cache manager");
spaceManager = gCacheManager->mMemSpaceManager;
PRUint32 occupancy;
rv = spaceManager->GetStorageInUse(&occupancy);
if (NS_FAILED(rv)) return rv;
PRUint32 memCacheCapacity = gCacheManager->mMemCacheCapacity;
if (occupancy > CACHE_HIGH_WATER_MARK(memCacheCapacity))
return spaceManager->Evict(CACHE_LOW_WATER_MARK(memCacheCapacity));
return NS_OK;
}
nsresult
nsCacheManager::LimitDiskCacheSize()
{
nsresult rv;
nsReplacementPolicy* spaceManager;
NS_ASSERTION(gCacheManager, "No cache manager");
spaceManager = gCacheManager->mDiskSpaceManager;
PRUint32 occupancy;
rv = spaceManager->GetStorageInUse(&occupancy);
if (NS_FAILED(rv)) return rv;
PRUint32 diskCacheCapacity = gCacheManager->mDiskCacheCapacity;
if (occupancy > CACHE_HIGH_WATER_MARK(diskCacheCapacity))
return spaceManager->Evict(CACHE_LOW_WATER_MARK(diskCacheCapacity));
return NS_OK;
}
nsresult
nsCacheManager::LimitCacheSize()
{
nsresult rv;
rv = LimitDiskCacheSize();
if (NS_FAILED(rv)) return rv;
rv = LimitMemCacheSize();
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::SetMemCacheCapacity(PRUint32 aCapacity)
{
mMemCacheCapacity = aCapacity;
LimitCacheSize();
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::GetMemCacheCapacity(PRUint32* aCapacity)
{
NS_ENSURE_ARG_POINTER(aCapacity);
*aCapacity = mMemCacheCapacity;
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::SetDiskCacheCapacity(PRUint32 aCapacity)
{
mDiskCacheCapacity = aCapacity;
LimitCacheSize();
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::GetDiskCacheCapacity(PRUint32* aCapacity)
{
NS_ENSURE_ARG_POINTER(aCapacity);
*aCapacity = mDiskCacheCapacity;
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::SetDiskCacheFolder(nsIFileSpec* aFolder)
{
NS_ENSURE_ARG(aFolder);
if (!mFileCache)
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<nsINetDataDiskCache> fileCache;
fileCache = do_QueryInterface(mFileCache);
return fileCache->SetDiskCacheFolder(aFolder);
}
NS_IMETHODIMP
nsCacheManager::GetDiskCacheFolder(nsIFileSpec* *aFolder)
{
NS_ENSURE_ARG(aFolder);
if (!mFileCache)
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<nsINetDataDiskCache> fileCache;
fileCache = do_QueryInterface(mFileCache);
return fileCache->GetDiskCacheFolder(aFolder);
}

View File

@@ -0,0 +1,100 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#ifndef _nsCacheManager_h_
#define _nsCacheManager_h_
// 2030f0b0-9567-11d3-90d3-0040056a906e
#define NS_CACHE_MANAGER_CID \
{ \
0x2030f0b0, \
0x9567, \
0x11d3, \
{0x90, 0xd3, 0x00, 0x40, 0x05, 0x6a, 0x90, 0x6e} \
}
#include "nsINetDataCacheManager.h"
#include "nsINetDataCache.h"
#include "nsCOMPtr.h"
class nsHashtable;
class nsReplacementPolicy;
class nsCachedNetData;
class nsCacheManager : public nsINetDataCacheManager {
public:
nsCacheManager();
virtual ~nsCacheManager();
NS_METHOD Init();
// nsISupports methods
NS_DECL_ISUPPORTS
// nsINetDataCacheManager methods
NS_DECL_NSINETDATACACHEMANAGER
private:
// Mapping from cache key to nsCachedNetData, but only for those cache
// entries with external references, i.e. those referred to outside the
// cache manager
nsHashtable* mActiveCacheRecords;
// Memory cache
nsCOMPtr<nsINetDataCache> mMemCache;
// Flat-file database cache; All content aggregated into single disk file
nsCOMPtr<nsINetDataCache> mFlatCache;
// stream-as-file cache
nsCOMPtr<nsINetDataCache> mFileCache;
// Unified replacement policy for flat-cache and file-cache
nsReplacementPolicy* mDiskSpaceManager;
// Replacement policy for memory cache
nsReplacementPolicy* mMemSpaceManager;
// List of caches in search order
nsINetDataCache* mCacheSearchChain;
// Combined file/flat cache capacity, in KB
PRUint32 mDiskCacheCapacity;
// Memory cache capacity, in KB
PRUint32 mMemCacheCapacity;
protected:
static nsresult NoteDormant(nsCachedNetData* aEntry);
static nsresult LimitCacheSize();
static nsresult LimitMemCacheSize();
static nsresult LimitDiskCacheSize();
friend class nsCachedNetData;
friend class CacheOutputStream;
};
#endif // _nsCacheManager_h_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,242 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#ifndef _nsCachedNetData_h_
#define _nsCachedNetData_h_
#include "nsICachedNetData.h"
#include "nsCOMPtr.h"
#include "nsINetDataCacheRecord.h"
class nsINetDataCache;
class nsIStreamAsFileObserver;
class nsIStreamAsFile;
class nsIArena;
class StreamAsFileObserverClosure;
class CacheMetaData;
// Number of recent access times recorded
#define MAX_K 3
/**
* FIXME - add comment. There are a lot of these data structures resident in
* memory, so be careful about adding members unnecessarily.
*/
class nsCachedNetData : public nsICachedNetData {
public:
NS_DECL_ISUPPORTS
// nsICachedNetData methods
NS_DECL_NSICACHEDNETDATA
NS_METHOD Init(nsINetDataCacheRecord *aRecord, nsINetDataCache *aCache);
protected:
// Bits for mFlags, below
typedef enum {
DIRTY = 1 << 0, // Cache entry data needs to be flushed to database
// ==== Flags that can be set by the protocol handler ====
ALLOW_PARTIAL = 1 << 1, // Protocol handler supports partial fetching
UPDATE_IN_PROGRESS = 1 << 2, // Protocol handler now modifying cache data
// ==== Cache-entry state flags. At most one of these flags can be set ====
TRUNCATED_CONTENT = 1 << 4, // Entry contains valid content, but it has
// been truncated by cache manager
// A previously-used cache entry, which has been purged of all cached
// content and protocol-private data. This cache entry can be refilled
// with new content or it may be retained in this vestigial state
// because the usage statistics it contains will be used by the
// replacement policy if the same URI is ever cached again.
VESTIGIAL = 1 << 5,
// ==== Memory usage status bits. At most one of these flags can be set ====
RECYCLED = 1 << 8, // Previously associated database record has
// been deleted; This cache entry is available
// for recycling.
DORMANT = 1 << 9, // No references to this cache entry, except by
// the cache manager itself
// ==== Setter bits ====
LAST_MODIFIED_KNOWN = 1 <<12, // Protocol handler called SetLastModifiedTime()
EXPIRATION_KNOWN = 1 <<13, // Protocol handler called SetExpirationTime()
STALE_TIME_KNOWN = 1 <<14, // Protocol handler called SetStaleTime()
// ==== Useful flag combinations ====
// Cache entry not eligible for eviction
UNEVICTABLE = VESTIGIAL | RECYCLED | UPDATE_IN_PROGRESS,
// State flags that are in-memory only, i.e. not persistent
TRANSIENT_FLAGS = DIRTY | RECYCLED | DORMANT
} Flag;
PRBool GetFlag(Flag aFlag) { return (mFlags & aFlag) != 0; }
nsresult GetFlag(PRBool *aResult, Flag aFlag) { *aResult = GetFlag(aFlag); return NS_OK; }
// Set a boolean flag for the cache entry
nsresult SetFlag(PRBool aValue, Flag aFlag);
nsresult SetFlag(Flag aFlag) { return SetFlag(PR_TRUE, aFlag); }
nsresult ClearFlag(Flag aFlag) { return SetFlag(PR_FALSE, aFlag); }
void ComputeProfit(PRUint32 aCurrentTime);
static int Compare(const void *a, const void *b, void *unused);
void NoteAccess();
void NoteUpdate();
// Get underlying raw cache database record.
nsresult GetRecord(nsINetDataCacheRecord* *aRecord);
nsresult GetRecordID(PRInt32 *aRecordID);
nsresult Evict(PRUint32 aTruncatedContentLength);
nsresult GetFileSpec(nsIFileSpec* *aFileSpec);
void NoteDownloadTime(PRTime start, PRTime end);
// placement new for arena-allocation
void *operator new (size_t aSize, nsIArena *aArena);
friend class nsReplacementPolicy;
friend class nsCacheManager;
friend class StreamAsFile;
friend class nsCacheEntryChannel;
friend class CacheOutputStream;
friend class InterceptStreamListener;
private:
nsCachedNetData() {};
virtual ~nsCachedNetData() {};
// Initialize internal fields of this nsCachedNetData instance from the
// underlying raw cache database record.
nsresult Deserialize(PRBool aDeserializeFlags);
// Notify stream-as-file observers about change in cache entry status
nsresult Notify(PRUint32 aMessage, nsresult aError);
// Add/Remove stream-as-file observers
nsresult AddObserver(nsIStreamAsFile *aStreamAsFile, nsIStreamAsFileObserver* aObserver);
nsresult RemoveObserver(nsIStreamAsFileObserver* aObserver);
// Mark cache entry to indicate a write out to the cache database is required
void SetDirty() { mFlags |= DIRTY; }
nsresult Resurrect(nsINetDataCacheRecord *aRecord);
nsresult CommitFlags();
CacheMetaData* FindTaggedMetaData(const char* aTag, PRBool aCreate);
private:
// List of nsIStreamAsFileObserver's that will receive notification events
// when the cache manager or a client desires to delete/truncate a cache
// entry file.
StreamAsFileObserverClosure* mObservers;
// Protocol-specific meta-data, opaque to the cache manager
CacheMetaData *mMetaData;
// Next in chain for a single bucket in the replacement policy hash table
// that maps from record ID to nsCachedNetData
nsCachedNetData* mNext;
// See flag bits, above
// NOTE: 16 bit member is combined with members below for
// struct packing efficiency. Do not change order of members!
PRUint16 mFlags;
protected:
// Number of nsCacheEntryChannels referring to this record
PRUint8 mChannelCount;
// Below members are statistics kept per cache-entry, used to decide how
// profitable it will be to evict a record from the cache relative to other
// existing records. Note: times are measured in *seconds* since the
// 1/1/70 epoch, same as a unix time_t.
// Number of accesses for this cache record
// NOTE: 8 bit member is combined with members above for
// struct packing efficiency. Do not change order of members!
PRUint8 mNumAccesses;
// A reference to the underlying, raw cache database record, either as a
// pointer to an in-memory object or as a database record identifier
union {
nsINetDataCacheRecord* mRecord;
// Database record ID of associated cache record. See
// nsINetDataCache::GetRecordByID().
PRInt32 mRecordID;
};
// Weak link to parent cache
nsINetDataCache* mCache;
// Length of stored content, which may be less than storage consumed if
// compression is used
PRUint32 mLogicalLength;
// Most recent cache entry access times, used to compute access frequency
PRUint32 mAccessTime[MAX_K];
// We use modification time of the original document for replacement policy
// computations, i.e. to compute a document's age, but if we don't know it,
// we use the time that the document was last written to the cache.
union {
// Document modification time, if known.
PRUint32 mLastModifiedTime;
// Time of last cache update for this doc
PRUint32 mLastUpdateTime;
};
union {
// Time until which document is fresh, i.e. does not have to be validated
// with server and, therefore, data in cache is guaranteed usable
PRUint32 mExpirationTime;
// Heuristic time at which cached document is likely to be out-of-date
// with respect to canonical copy on server. Used for cache replacement
// policy, not for validation.
PRUint32 mStaleTime;
};
// Download time per byte, measure roughly in units of KB/s
float mDownloadRate;
// Heuristic estimate of cache entry future benefits, based on above values
float mProfit;
};
#endif // _nsCachedNetData_h_

View File

@@ -0,0 +1,666 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#include "nsReplacementPolicy.h"
#include "nsCachedNetData.h"
#include "nsQuickSort.h"
#include "nsIAllocator.h"
#include "nsIEnumerator.h"
#include "prtime.h"
#include "prbit.h"
#include "nsCOMPtr.h"
#include <math.h>
// Constant used to estimate frequency of access to a document based on size
#define CACHE_CONST_B 1.35
// A cache whose space is managed by this replacement policy
class nsReplacementPolicy::CacheInfo {
public:
CacheInfo(nsINetDataCache* aCache):mCache(aCache),mNext(0) {}
nsINetDataCache* mCache;
CacheInfo* mNext;
};
nsReplacementPolicy::nsReplacementPolicy()
: mRankedEntries(0), mCaches(0), mRecordsRemovedSinceLastRanking(0),
mNumEntries(0), mCapacityRankedEntriesArray(0), mLastRankTime(0) {}
nsReplacementPolicy::~nsReplacementPolicy()
{
if (mRankedEntries)
nsAllocator::Free(mRankedEntries);
if (mMapRecordIdToEntry)
nsAllocator::Free(mMapRecordIdToEntry);
}
nsresult
nsReplacementPolicy::Init(PRUint32 aMaxCacheEntries)
{
nsresult rv;
rv = NS_NewHeapArena(getter_AddRefs(mArena), sizeof(nsCachedNetData) * 32);
if (NS_FAILED(rv)) return rv;
mMaxEntries = aMaxCacheEntries;
mHashArrayLength = PR_CeilingLog2(aMaxCacheEntries) >> 3;
size_t numBytes = mHashArrayLength * sizeof(*mMapRecordIdToEntry);
mMapRecordIdToEntry = (nsCachedNetData**)nsAllocator::Alloc(numBytes);
if (!mMapRecordIdToEntry)
return NS_ERROR_OUT_OF_MEMORY;
nsCRT::zero(mMapRecordIdToEntry, numBytes);
return NS_OK;
}
nsresult
nsReplacementPolicy::AddCache(nsINetDataCache *aCache)
{
CacheInfo *cacheInfo = new CacheInfo(aCache);
if (!cacheInfo)
return NS_ERROR_OUT_OF_MEMORY;
cacheInfo->mNext = mCaches;
mCaches = cacheInfo;
return NS_OK;
}
PRUint32
nsReplacementPolicy::HashRecordID(PRInt32 aRecordID)
{
return ((aRecordID >> 16) ^ aRecordID) & (mHashArrayLength - 1);
}
nsCachedNetData*
nsReplacementPolicy::FindCacheEntryByRecordID(PRInt32 aRecordID, nsINetDataCache *aCache)
{
nsresult rv;
nsCachedNetData* cacheEntry;
PRUint32 bucket = HashRecordID(aRecordID);
cacheEntry = mMapRecordIdToEntry[bucket];
for (;cacheEntry; cacheEntry = cacheEntry->mNext) {
PRInt32 recordID;
rv = cacheEntry->GetRecordID(&recordID);
if (NS_FAILED(rv))
continue;
if ((recordID == aRecordID) && (cacheEntry->mCache == aCache))
return cacheEntry;
}
return 0;
}
// Add a cache entry to the hash table that maps record ID to entries
void
nsReplacementPolicy::AddCacheEntry(nsCachedNetData* aCacheEntry, PRInt32 aRecordID)
{
nsCachedNetData** cacheEntryp;
PRUint32 bucket = HashRecordID(aRecordID);
cacheEntryp = &mMapRecordIdToEntry[bucket];
while (*cacheEntryp)
cacheEntryp = &(*cacheEntryp)->mNext;
*cacheEntryp = aCacheEntry;
aCacheEntry->mNext = 0;
}
// Delete a cache entry from the hash table that maps record ID to entries
nsresult
nsReplacementPolicy::DeleteCacheEntry(nsCachedNetData* aCacheEntry)
{
nsresult rv;
PRInt32 recordID;
rv = aCacheEntry->GetRecordID(&recordID);
if (NS_FAILED(rv)) return rv;
PRUint32 bucket = HashRecordID(recordID);
nsCachedNetData** cacheEntryp;
cacheEntryp = &mMapRecordIdToEntry[bucket];
while (*cacheEntryp) {
if (*cacheEntryp == aCacheEntry) {
*cacheEntryp = aCacheEntry->mNext;
return NS_OK;
}
cacheEntryp = &(*cacheEntryp)->mNext;
}
NS_ASSERTION(0, "hash table inconsistency");
return NS_ERROR_FAILURE;
}
nsresult
nsReplacementPolicy::AddAllRecordsInCache(nsINetDataCache *aCache)
{
nsresult rv;
nsCOMPtr<nsISimpleEnumerator> iterator;
nsCOMPtr<nsISupports> iSupports;
nsCOMPtr<nsINetDataCacheRecord> record;
rv = aCache->NewCacheEntryIterator(getter_AddRefs(iterator));
if (!NS_SUCCEEDED(rv)) return rv;
while (1) {
PRBool notDone;
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
rv = iterator->GetNext(getter_AddRefs(iSupports));
if (!NS_SUCCEEDED(rv)) return rv;
record = do_QueryInterface(iSupports);
rv = AssociateCacheEntryWithRecord(record, aCache, 0);
if (!NS_SUCCEEDED(rv)) return rv;
}
return NS_OK;
}
// Get current time and convert to seconds since the epoch
static PRUint32
now32()
{
double nowFP;
PRInt64 now64 = PR_Now();
LL_L2D(nowFP, now64);
PRUint32 now = (PRUint32)(nowFP * 1e-6);
return now;
}
void
nsCachedNetData::NoteDownloadTime(PRTime start, PRTime end)
{
double startFP, endFP, rate, duration;
LL_L2D(startFP, start);
LL_L2D(endFP, end);
duration = endFP - startFP;
// If the data arrives so fast that it can not be timed due to the clock
// granularity, assume a data arrival duration of 10 ms
if (!duration)
duration = 10000;
// Compute download rate in kB/s
rate = mLogicalLength / (duration * (1e-6 * 1024.0));
if (mDownloadRate) {
// Exponentially smooth download rate
const double alpha = 0.5;
mDownloadRate = (float)(mDownloadRate * alpha + rate * (1.0 - alpha));
} else {
mDownloadRate = (float)rate;
}
}
// 1 hour
#define MIN_HALFLIFE (60 * 60)
// 1 week
#define TYPICAL_HALFLIFE (7 * 24 * 60 * 60)
/**
* Estimate the profit that would be lost if the given cache entry was evicted
* from the cache. Profit is defined as the future expected download delay per
* byte of cached content. The profit computation is made based on projected
* frequency of access, prior download performance and a heuristic staleness
* criteria. The technique used is a variation of that described in the
* following paper:
*
* "A Case for Delay-Conscious Caching of Web Documents"
* http://www.bell-labs.com/user/rvingral/www97.html
*
* Briefly, expected profit is:
*
* (projected frequency of access) * (download time per byte) * (probability freshness)
*/
void
nsCachedNetData::ComputeProfit(PRUint32 aNow)
{
PRUint32 K, now;
if (aNow)
now = aNow;
else
now = now32();
K = PR_MIN(MAX_K, mNumAccesses);
if (!K) {
mProfit = 0;
return;
}
// Compute time, in seconds, since k'th most recent access
double timeSinceKthAccess = now - mAccessTime[K - 1];
if (timeSinceKthAccess <= 0.0) // Sanity check
timeSinceKthAccess = 1.0;
// Estimate frequency of future document access based on past
// access frequency
double frequencyAccess = K / timeSinceKthAccess;
// If we don't have much historical data on access frequency
// use a heuristic based on document size as an estimate
if (mLogicalLength) {
if (K == 1) {
frequencyAccess /= pow(mLogicalLength, CACHE_CONST_B);
} else if (K == 2) {
frequencyAccess /= pow(mLogicalLength, CACHE_CONST_B / 2);
}
}
// Estimate likelihood that data in cache is fresh, i.e.
// that it corresponds to the document on the server
double probabilityFreshness;
PRInt32 halfLife, age, docTime;
PRBool potentiallyStale;
docTime = GetFlag(LAST_MODIFIED_KNOWN) ? mLastModifiedTime : mLastUpdateTime;
age = now - docTime;
probabilityFreshness = 1.0; // Optimistic
if (GetFlag(EXPIRATION_KNOWN)) {
potentiallyStale = now > mExpirationTime;
halfLife = mExpirationTime - mLastModifiedTime;
} else if (GetFlag(STALE_TIME_KNOWN)) {
potentiallyStale = PR_TRUE;
halfLife = mStaleTime - docTime;
} else {
potentiallyStale = PR_TRUE;
halfLife = TYPICAL_HALFLIFE;
}
if (potentiallyStale) {
if (halfLife < MIN_HALFLIFE)
halfLife = MIN_HALFLIFE;
probabilityFreshness = pow(0.5, (double)age / (double)halfLife);
}
mProfit = (float)(frequencyAccess * probabilityFreshness);
if (mDownloadRate)
mProfit /= mDownloadRate;
}
// Number of entries to grow mRankedEntries array when it's full
#define STATS_GROWTH_INCREMENT 256
// Sorting predicate for NS_Quicksort
int
nsCachedNetData::Compare(const void *a, const void *b, void *unused)
{
nsCachedNetData* entryA = *(nsCachedNetData**)a;
nsCachedNetData* entryB = *(nsCachedNetData**)b;
// Percolate deleted or empty entries to the end of the mRankedEntries
// array, so that they can be recycled.
if (!entryA || entryA->GetFlag(RECYCLED)) {
if (!entryB || entryB->GetFlag(RECYCLED))
return 0;
else
return +1;
}
if (!entryB || entryB->GetFlag(RECYCLED))
return -1;
// Evicted entries (those with no content data) and active entries (those
// currently being updated) are collected towards the end of the sorted
// array just prior to the deleted cache entries, since evicted entries
// can't be re-evicted.
if (entryA->GetFlag(UPDATE_IN_PROGRESS)) {
if (entryB->GetFlag(UPDATE_IN_PROGRESS))
return 0;
else
return +1;
}
if (entryB->GetFlag(UPDATE_IN_PROGRESS))
return -1;
PRUint16 Ka = PR_MIN(MAX_K, entryA->mNumAccesses);
PRUint16 Kb = PR_MIN(MAX_K, entryB->mNumAccesses);
// Order cache entries by the number of times they've been accessed
if (Ka < Kb)
return -1;
if (Ka > Kb)
return +1;
/*
* Among records that have been accessed an equal number of times, order
* them by profit.
*/
if (entryA->mProfit > entryB->mProfit)
return +1;
if (entryA->mProfit < entryB->mProfit)
return -1;
return 0;
}
/**
* Rank cache entries in terms of their elegibility for eviction.
*/
nsresult
nsReplacementPolicy::RankRecords()
{
PRUint32 i, now;
// Add all cache records if this is the first ranking
if (!mLastRankTime) {
nsresult rv;
CacheInfo *cacheInfo;
cacheInfo = mCaches;
while (cacheInfo) {
rv = AddAllRecordsInCache(cacheInfo->mCache);
if (NS_FAILED(rv)) return rv;
cacheInfo = cacheInfo->mNext;
}
}
// Get current time and convert to seconds since the epoch
now = now32();
// Recompute profit for every known cache record, except deleted ones
for (i = 0; i < mNumEntries; i++) {
nsCachedNetData* entry = mRankedEntries[i];
if (entry && !entry->GetFlag(nsCachedNetData::RECYCLED))
entry->ComputeProfit(now);
}
NS_QuickSort(mRankedEntries, mNumEntries, sizeof *mRankedEntries,
nsCachedNetData::Compare, 0);
mNumEntries -= mRecordsRemovedSinceLastRanking;
mRecordsRemovedSinceLastRanking = 0;
mLastRankTime = now;
return NS_OK;
}
// A heuristic policy to avoid the cost of re-ranking cache records by
// profitability every single time space must be made available in the cache.
void
nsReplacementPolicy::MaybeRerankRecords()
{
// Rank at most once per minute
PRUint32 now = now32();
if ((now - mLastRankTime) >= 60)
RankRecords();
}
void
nsReplacementPolicy::CompactRankedEntriesArray()
{
if (mRecordsRemovedSinceLastRanking || !mLastRankTime)
RankRecords();
}
nsresult
nsReplacementPolicy::CheckForTooManyCacheEntries()
{
if (mCapacityRankedEntriesArray == mMaxEntries) {
return DeleteOneEntry(0);
} else {
nsresult rv;
CacheInfo *cacheInfo;
cacheInfo = mCaches;
while (cacheInfo) {
PRUint32 numEntries, maxEntries;
rv = cacheInfo->mCache->GetNumEntries(&numEntries);
if (NS_FAILED(rv)) return rv;
rv = cacheInfo->mCache->GetMaxEntries(&maxEntries);
if (NS_FAILED(rv)) return rv;
if (numEntries == maxEntries)
return DeleteOneEntry(cacheInfo->mCache);
cacheInfo = cacheInfo->mNext;
}
}
return NS_OK;
}
/**
* Create a new association between a low-level cache database record and a
* cache entry. Add the entry to the set of entries eligible for eviction from
* the cache. This would typically be done when the cache entry is created.
*/
nsresult
nsReplacementPolicy::AssociateCacheEntryWithRecord(nsINetDataCacheRecord *aRecord,
nsINetDataCache* aCache,
nsCachedNetData** aResult)
{
nsCachedNetData* cacheEntry;
nsresult rv;
// First, see if the record is already known to the replacement policy
PRInt32 recordID;
rv = aRecord->GetRecordID(&recordID);
if (NS_FAILED(rv)) return rv;
cacheEntry = FindCacheEntryByRecordID(recordID, aCache);
if (cacheEntry) {
if (aResult) {
if (cacheEntry->GetFlag(nsCachedNetData::DORMANT))
cacheEntry->Resurrect(aRecord);
NS_ADDREF(cacheEntry);
*aResult = cacheEntry;
}
return NS_OK;
}
// Compact the array of cache entry statistics, so that free entries appear
// at the end, for possible reuse.
if (mNumEntries && (mNumEntries == mCapacityRankedEntriesArray))
CompactRankedEntriesArray();
// If compaction doesn't yield available entries in the
// mRankedEntries array, then extend the array.
if (mNumEntries == mCapacityRankedEntriesArray) {
PRUint32 newCapacity;
rv = CheckForTooManyCacheEntries();
if (NS_FAILED(rv)) return rv;
newCapacity = mCapacityRankedEntriesArray + STATS_GROWTH_INCREMENT;
if (newCapacity > mMaxEntries)
newCapacity = mMaxEntries;
nsCachedNetData** newRankedEntriesArray;
PRUint32 numBytes = sizeof(nsCachedNetData*) * newCapacity;
newRankedEntriesArray =
(nsCachedNetData**)nsAllocator::Realloc(mRankedEntries, numBytes);
if (!newRankedEntriesArray)
return NS_ERROR_OUT_OF_MEMORY;
mRankedEntries = newRankedEntriesArray;
mCapacityRankedEntriesArray = newCapacity;
PRUint32 i;
for (i = mNumEntries; i < newCapacity; i++)
mRankedEntries[i] = 0;
}
// Recycle the record after the last in-use record in the array
nsCachedNetData *entry = mRankedEntries[mNumEntries];
NS_ASSERTION(!entry || !entry->GetFlag(nsCachedNetData::RECYCLED),
"Only deleted cache entries should appear at end of array");
if (!entry) {
entry = new(mArena) nsCachedNetData;
if (!entry)
return NS_ERROR_OUT_OF_MEMORY;
mRankedEntries[mNumEntries] = entry;
} else {
// Clear out recycled data structure
nsCRT::zero(entry, sizeof(*entry));
}
entry->Init(aRecord, aCache);
AddCacheEntry(entry, recordID);
// Add one reference to the cache entry from the cache manager
NS_ADDREF(entry);
if (aResult) {
// And one reference from our caller
NS_ADDREF(entry);
*aResult = entry;
}
mNumEntries++;
return NS_OK;
}
nsresult
nsReplacementPolicy::GetCachedNetData(const char* cacheKey, PRUint32 cacheKeyLength,
nsINetDataCache* aCache,
nsCachedNetData** aResult)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
rv = aCache->GetCachedNetData(cacheKey, cacheKeyLength,
getter_AddRefs(record));
if (NS_FAILED(rv)) return rv;
return AssociateCacheEntryWithRecord(record, aCache, aResult);
}
/**
* Delete the least desirable record from the cache database. This is used
* when the addition of another record would exceed either the cache manager or
* the cache's maximum permitted number of records.
*/
nsresult
nsReplacementPolicy::DeleteOneEntry(nsINetDataCache *aCache)
{
PRUint32 i;
nsresult rv;
nsCachedNetData *entry;
i = 0;
while (1) {
MaybeRerankRecords();
for (; i < mNumEntries; i++) {
entry = mRankedEntries[i];
if (!entry || entry->GetFlag(nsCachedNetData::RECYCLED))
continue;
if (!aCache || (entry->mCache == aCache))
break;
}
// Report error if no record found to delete
if (i == mNumEntries)
return NS_ERROR_FAILURE;
rv = entry->Delete();
if (NS_SUCCEEDED(rv)) {
rv = DeleteCacheEntry(entry);
return rv;
}
}
}
nsresult
nsReplacementPolicy::GetStorageInUse(PRUint32* aStorageInUse)
{
nsresult rv;
CacheInfo *cacheInfo;
*aStorageInUse = 0;
cacheInfo = mCaches;
while (cacheInfo) {
PRUint32 cacheStorage;
rv = cacheInfo->mCache->GetStorageInUse(&cacheStorage);
if (NS_FAILED(rv)) return rv;
*aStorageInUse += cacheStorage;
cacheInfo = cacheInfo->mNext;
}
return NS_OK;
}
/**
* Delete the least desirable records from the cache until the occupancy of the
* cache has been reduced by the given number of KB. This is used when the
* addition of more cache data would exceed the cache's capacity.
*/
nsresult
nsReplacementPolicy::Evict(PRUint32 aTargetOccupancy)
{
PRUint32 i;
nsCachedNetData *entry;
nsresult rv;
PRUint32 occupancy;
PRInt32 truncatedLength;
nsCOMPtr<nsINetDataCacheRecord> record;
MaybeRerankRecords();
for (i = 0; i < mNumEntries; i++) {
rv = GetStorageInUse(&occupancy);
if (!NS_SUCCEEDED(rv)) return rv;
if (occupancy <= aTargetOccupancy)
return NS_OK;
entry = mRankedEntries[i];
// Skip deleted/empty cache entries and ones that have already been evicted
if (!entry || entry->GetFlag(nsCachedNetData::UNEVICTABLE))
continue;
if (entry->GetFlag(nsCachedNetData::ALLOW_PARTIAL)) {
rv = entry->GetRecord(getter_AddRefs(record));
if (NS_FAILED(rv))
continue;
PRUint32 contentLength;
rv = record->GetStoredContentLength(&contentLength);
if (NS_FAILED(rv))
continue;
// Additional cache storage required, in KB
PRUint32 storageToReclaim = (occupancy - aTargetOccupancy) << 10;
truncatedLength = (PRInt32)(contentLength - storageToReclaim);
if (truncatedLength < 0)
truncatedLength = 0;
} else {
truncatedLength = 0;
}
rv = entry->Evict(truncatedLength);
}
return NS_ERROR_FAILURE;
}

View File

@@ -0,0 +1,136 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
/**
* This class manages one or more caches that share a storage resource, e.g. a
* file cache and a flat-database cache might each occupy space on the disk and
* they would share a single instance of nsReplacementPolicy. The replacement
* policy heuristically chooses which cache entries to evict when storage is
* required to accommodate incoming cache data.
*/
#ifndef _nsReplacementPolicy_h_
#define _nsReplacementPolicy_h_
#include "nscore.h"
#include "nsISupportsUtils.h"
#include "nsINetDataCache.h"
#include "nsICachedNetData.h"
#include "nsIArena.h"
#include "nsCOMPtr.h"
#include "nsHashtable.h"
class nsCachedNetData;
struct PL_HashTable;
/**
* This private class is responsible for implementing the network data cache's
* replacement policy, i.e. it decides which cache data should be evicted to
* make room for new incoming data.
*/
class nsReplacementPolicy {
public:
nsReplacementPolicy();
~nsReplacementPolicy();
protected:
nsresult Init(PRUint32 aMaxCacheEntries);
nsresult AddCache(nsINetDataCache *aCache);
nsresult GetCachedNetData(const char* cacheKey, PRUint32 cacheKeyLength,
nsINetDataCache* aCache,
nsCachedNetData** aResult);
nsresult GetStorageInUse(PRUint32* aNumKBytes);
friend class nsCacheManager;
private:
nsresult RankRecords();
void MaybeRerankRecords();
void CompactRankedEntriesArray();
nsresult DeleteOneEntry(nsINetDataCache* aCache);
nsresult Evict(PRUint32 aTargetOccupancy);
nsCachedNetData* FindCacheEntryByRecordID(PRInt32 aRecordID, nsINetDataCache *aCache);
void AddCacheEntry(nsCachedNetData* aCacheEntry, PRInt32 aRecordID);
nsresult DeleteCacheEntry(nsCachedNetData* aCacheEntry);
PRUint32 HashRecordID(PRInt32 aRecordID);
nsresult AssociateCacheEntryWithRecord(nsINetDataCacheRecord *aRecord,
nsINetDataCache* aCache,
nsCachedNetData** aResult);
nsresult AddAllRecordsInCache(nsINetDataCache *aCache);
nsresult CheckForTooManyCacheEntries();
class CacheInfo;
private:
// Growable array of pointers to individual cache entries; It is sorted by
// profitability, such that low-numbered array indices refer to cache
// entries that are the least profitable to retain. New cache entries are
// added to the end of the array. Deleted cache entries are specially
// marked and percolate to the end of the array for recycling whenever
// mRankedEntries is sorted. Evicted cache entries (those with no
// associated content data) are retained for the purpose of improving the
// replacement policy efficacy, and are percolated towards the end of the
// array, just prior to the deleted cache entries.
//
// The array is not in sorted order 100% of the time; For efficiency
// reasons, sorting is only done when heuristically deemed necessary.
nsCachedNetData** mRankedEntries;
// Hash table buckets to map Record ID to cache entry. We use this instead
// of a PL_HashTable to reduce storage requirements
nsCachedNetData** mMapRecordIdToEntry;
// Length of mMapRecordIdToEntry array
PRUint32 mHashArrayLength;
// Linked list of caches that share this replacement policy
CacheInfo* mCaches;
// Allocation area for cache entry (nsCachedNetData) instances
nsCOMPtr<nsIArena> mArena;
// Bookkeeping
PRUint32 mRecordsRemovedSinceLastRanking;
// Maximum permitted length of mRankedEntries array
PRUint32 mMaxEntries;
// Number of occupied slots in mRankedEntries array
PRUint32 mNumEntries;
// Capacity of mRankedEntries array
PRUint32 mCapacityRankedEntriesArray;
// Time at which cache entries were last ranked by profitability
PRUint32 mLastRankTime;
};
#endif // _nsReplacementPolicy_h_

View File

@@ -0,0 +1,43 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
MODULE = nkcache
include $(DEPTH)/config/autoconf.mk
XPIDLSRCS = \
nsICachedNetData.idl \
nsINetDataCacheManager.idl \
nsINetDataCache.idl \
nsINetDataCacheRecord.idl \
nsINetDataDiskCache.idl \
nsIStreamAsFile.idl \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
include $(topsrcdir)/config/rules.mk

41
mozilla/netwerk/cache/public/Makefile.win vendored Executable file
View File

@@ -0,0 +1,41 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
MODULE = nkcache
DEPTH = ..\..\..
include <$(DEPTH)/config/config.mak>
EXPORTS = \
$(NULL)
XPIDLSRCS = \
.\nsICachedNetData.idl \
.\nsINetDataCacheManager.idl \
.\nsINetDataCache.idl \
.\nsINetDataCacheRecord.idl \
.\nsINetDataDiskCache.idl \
.\nsIStreamAsFile.idl \
$(NULL)
include <$(DEPTH)/config/rules.mak>

View File

@@ -0,0 +1,229 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsrootidl.idl"
#include "nsISupports.idl"
interface nsIFileSpec;
interface nsIURI;
interface nsIObserver;
interface nsIChannel;
interface nsINetDataCache;
interface nsINetDataCacheRecord;
interface nsILoadGroup;
interface nsIStreamListener;
/**
* The nsICachedNetData interface represents a single entry in a database that
* caches data retrieved from the network. This interface is implemented by the
* cache manager on top of the low-level nsINetDataCacheRecord and
* nsINetDataCache interfaces that are implemented by the database.
*
* Each cache record may contain both content and metadata. The content may
* be, for example, GIF image data or HTML, and it is accessed through
* nsIChannel's streaming API. The opaque metadata, which may contain HTTP
* headers among other things, is stored as a byte array. Each entry in the
* cache is indexed by two different keys: a record id number and a key created
* by combining the URI with a "secondary key", e.g. HTTP post data.
*
* @See nsINetDataCacheRecord
* @See nsINetDataCache
* @See nsINetDataDiskCache
* @See nsINetDataCacheManager
*/
[scriptable, uuid(6aeb2a40-6d43-11d3-90c8-000064657374)]
interface nsICachedNetData : nsISupports
{
/**
* String form of the URI provided as an argument to the call to
* nsINetDataCacheManager::GetCachedNetData() that created this record.
*/
readonly attribute string uriSpec;
/**
* Getter for the opaque secondary database key provided as an argument to
* the call to nsINetDataCacheManager::GetCachedNetData() that created this
* record.
*/
void getSecondaryKey(out unsigned long length,
[retval, size_is(length)] out string secondaryKey);
/**
* This flag may be set by a protocol handler to indicate that it supports
* partial fetching of data. In that case, the cache manager is permitted
* to truncate the entry's content to accommodate incoming data for other
* cache entries rather than deleting it wholesale.
*/
attribute boolean allowPartial;
/**
* This flag indicates that the write stream supplying content data for the
* cache did not complete normally and, therefore, the content may be
* truncated.
*/
readonly attribute boolean partialFlag;
/**
* This flag can be set and cleared by a protocol handler as a form of
* self-notification, so as to avoid race conditions in which a protocol
* handler issues two identical network requests to fill the same cache
* entry. The cache manager itself largely ignores this flag.
*/
attribute boolean updateInProgress;
/**
* inUse is set if any existing channels are associated with this cache
* entry or if the updateInProgess flag is set. This can be used to
* prevent writing to a cache entry by a protocol handler if it's being
* read or written elsewhere.
*/
readonly attribute boolean inUse;
/**
* Date/time that the document was last stored on the origin server, as
* supplied by the protocol handler. This value is used as input to the
* cache replacement policy, i.e. it is not used for validation. If the
* protocol can't supply a last-modified time, this attribute should remain
* unset. When unset, the value of this attribute is zero.
*
* FIXME: Should use nsIDateTime interface, once it's created
* instead of PRTime, for improved scriptability ?
*/
attribute PRTime lastModifiedTime;
/**
* Supplied by the protocol handler, the expirationTime attribute specifies
* the time until which the document is guaranteed fresh, i.e. the document
* does not have to be validated with the server and, therefore, any data
* in cache is definitely usable. The value of this attribute serves as a
* hint to the cache replacement policy. Only one of either staleTime or
* expirationTime may be set for a single cache record. When unset, the
* value of this attribute is zero.
*/
attribute PRTime expirationTime;
/**
* Date/time supplied by the protocol handler, at which point the content
* is *likely* to be stale, i.e. the data in the cache may be out-of-date
* with respect to the data on the server. This heuristic date does not
* necessarily correspond to the HTTP Expires header, as it does not
* determine when cached network data must be validated with the origin
* server, but only serves as a hint to the cache replacement policy. Only
* one of either staleTime or expirationTime may be set for a single cache
* record. When unset, the value of this attribute is zero.
*/
attribute PRTime staleTime;
/**
* Date/time of last access of the data in this cache record, as determined
* by the cache manager.
*/
readonly attribute PRTime lastAccessTime;
/**
* Number of times this record has been accessed since it was first stored.
*/
readonly attribute PRUint16 numberAccesses;
/**
* Accessor methods for opaque meta-data which can be read and updated
* independently of the content data.
*
* The aTag argument can be used to accommodate multiple clients of the
* cache API, each of which wants to store its own private meta-data into
* the cache. For example, there could be a "headers" tag that the HTTP
* protocol handler uses to store http response headers and a "image size"
* tag used to store the image dimensions of a GIF file. The aData
* argument refers to an opaque blob of arbitrary bytes.
*
* IMPORTANT: If aData does not contain byte-oriented data, i.e. it's not a
* string, the contents of aData must be byte-swapped by the,
* caller, so as to make the cache files endian-independent.
*/
void getAnnotation(in string aTag,
out PRUint32 aLength, [size_is(aLength), retval] out string aData);
void setAnnotation(in string aTag,
in PRUint32 aLength, [size_is(aLength)] in string aData);
/**
* As a getter, return the number of content bytes stored in the cache,
* i.e. via the nsIChannel streaming APIs. This may be less than the
* complete content length if a partial cache fill occurred. The cached
* content can be truncated by setting the value of this attribute. The
* value of the attribute represents a logical, not a physical, length. If
* compression has been used, the content may consume less storage than
* indicated by this attribute.
*
* When this attribute is set to zero the associated cache disk file, if
* any, should be deleted.
*/
attribute PRUint32 storedContentLength;
/**
* Notify any observers associated with this cache entry of the deletion
* request. If all observers drop their reference to the cache entry,
* proceed to delete the underlying cache database record and associated
* content storage.
*/
void delete();
/**
* Flush any changes in this entry's data to the cache database. This
* method will automatically be called when the last reference to the cache
* is dropped, but it can also be called explicitly for a synchronous
* effect.
*/
void commit();
/**
* Parent container cache for this entry.
*/
readonly attribute nsINetDataCache cache;
/**
* Create a channel for reading or writing a stream of content into the
* entry. It is expected that many of the nsIChannel methods return
* NS_NOT_IMPLEMENTED, including:
*
* + GetURI()
* + GetContentType()
* + GetContentLength()
*
* Though nsIChannel provides for both async and synchronous I/O APIs, both
* may not be implemented. Only AsyncRead() and OpenOutputStream() is
* required. The aProxyChannel argument allows another channel to be
* specified as the proffered argument to nsIStreamListener methods rather
* than the cache's own channel.
*/
nsIChannel newChannel(in nsILoadGroup aLoadGroup,
in nsIChannel aProxyChannel);
/**
* This method can be used by a caching protocol handler to store data in
* the cache by forking an asynchronous read stream so that it is
* simultaneously sent to a requester and written into the cache. This
* method implicitly sets the updateInProgress flag, if it has not already
* been set.
*/
nsIStreamListener interceptAsyncRead(in nsIStreamListener aOriginalListener,
in PRUint32 aStartOffset);
};

View File

@@ -0,0 +1,143 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsISupports.idl"
interface nsIURI;
interface nsINetDataCacheRecord;
interface nsISimpleEnumerator;
interface nsIFileSpec;
/**
* The nsINetDataCache defines the low-level API for a network-data
* cache, used to cache the responses to network retrieval commands.
* This interface, along with nsINetDataCacheRecord, is implemented by
* the memory cache, the file cache and, optionally, by some extension
* caches. This interface is essentially a pseudo-private API for the
* cache manager. Other clients should never use this interface.
*
* Each cache entry may contain both content, e.g. GIF image data, and
* associated metadata, e.g. HTTP headers. Each entry is indexed by two
* different keys: a record id number and a key created by combining the URI
* with a "secondary key", e.g. HTTP post data.
*
* The nsINetDataCache interface is agnostic as to where the data is
* stored and whether the storage is volatile or persistent. The
* memory cache, any disk caches and any extension caches must all
* implement this interface.
*
*/
[scriptable, uuid(ccfc58c0-6dde-11d3-90c8-000064657374)]
interface nsINetDataCache : nsISupports
{
/**
* Human-readable description of the cache module, e.g. "Disk Cache"
*/
readonly attribute wstring description;
/**
* Returns true if cached data is available for the given opaque key,
* even if only partial data is stored.
*/
boolean contains([size_is(length)] in string key, in PRUint32 length);
/**
* Fetch the cache entry record for the given opaque key. If one does not
* exist, create a new, empty record.
*/
nsINetDataCacheRecord getCachedNetData([size_is(length)] in string key,
in PRUint32 length);
/**
* Fetch the cache entry record for the given URI using the record ID as a key.
*/
nsINetDataCacheRecord getCachedNetDataByID(in PRInt32 RecordID);
/**
* False indicates that this cache is entirely bypassed.
*/
attribute boolean enabled;
/**
* Constants for flags attribute, below
*/
// Used for extension caches, e.g. a CD-ROM cache
const long READ_ONLY = 1 << 0;
// One of these bits must be set
const long MEMORY_CACHE = 1 << 1;
const long FLAT_FILE_CACHE = 1 << 2;
const long FILE_PER_URL_CACHE = 1 << 3;
/**
* See constants defined above.
*/
readonly attribute PRUint32 flags;
/**
* Total number of URI entries stored in the cache.
*/
readonly attribute PRUint32 numEntries;
/**
* Maximum number of URI entries that may be stored in the cache.
*/
readonly attribute PRUint32 maxEntries;
/**
* Enumerate the URI entries stored in the cache.
*/
nsISimpleEnumerator newCacheEntryIterator();
/**
* Contains a reference to the next cache in search order. For the memory
* cache, this attribute always references the disk cache. For the disk
* cache, it contains a reference to the first extension cache.
*/
attribute nsINetDataCache nextCache;
/**
* An estimate of the amount of storage occupied by the cache, in kB.
* Actual use may be slightly higher than reported due to cache overhead
* and heap fragmentation (in the memory cache) or block quantization (in
* the disk cache).
*/
readonly attribute PRUint32 storageInUse;
/**
* Remove all entries from a writable cache. This could be used, for
* example, after a guest ends a browser session. This is equivalent to
* setting the cache's Capacity to zero, except that all cache entries,
* even those in active use, will be deleted. Also, any global cache
* database files will be deleted.
*/
void removeAll();
};
%{ C++
// ProgID prefix for Components that implement this interface
#define NS_NETWORK_CACHE_PROGID "component://netscape/network/cache"
#define NS_NETWORK_MEMORY_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=memory-cache"
#define NS_NETWORK_FLAT_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=flat-cache"
#define NS_NETWORK_FILE_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=file-cache"
%}

View File

@@ -0,0 +1,163 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsISupports.idl"
interface nsISimpleEnumerator;
interface nsICachedNetData;
interface nsINetDataCache;
interface nsINetDataDiskCache;
interface nsIURI;
interface nsIFileSpec;
/**
* The network-response cache manager is partly responsible for the caching of
* content and associated metadata that has been retrieved via the network.
* (The remaining responsibility for caching lies with individual network
* protocol handlers.)
*
* The cache manager supervises the actions of individual cache components,
* such as the memory cache, the disk cache and any extension caches, e.g. a
* read-only CD-ROM cache.
*
* @See nsINetDataCache
* @See nsICachedNetData
*/
[scriptable, uuid(71c8ab00-6d5c-11d3-90c8-000064657374)]
interface nsINetDataCacheManager : nsISupports
{
/**
* Flag for the GetCachedNetData() method: If set, the memory cache is
* neither searched nor will any data be stored into it. This might be
* appropriate, for example, with images, because they have their own
* cache for storing *decoded* images.
*/
const unsigned long BYPASS_MEMORY_CACHE = 1 << 0;
/**
* Flag for the GetCachedNetData() method: If set, the disk cache
* is neither searched nor will any be data stored into it.
* However, read-only extension caches may be searched. This
* might be used to avoid leaving persistent records of secure
* data.
*/
const unsigned long BYPASS_PERSISTENT_CACHE = 1 << 1;
/**
* Flag for the GetCachedNetData() method: If set, any stream
* content is stored in the cache as a single disk file. Content
* will not be cached in the memory cache nor is it cached in a
* flat-file cache database. This is used to implement the jar
* protocol handler and to provide the stream-as-file semantics
* required by the classic bowser plugin API.
*/
const unsigned long CACHE_AS_FILE = 1 << 2;
/**
* Fetch the cache entry record for the given URI. If one does not exist,
* create a new, empty record. The normal search order for caches is:
* + Memory cache
* + Disk cache
* + File cache (stream-as-file cache)
* + All extension caches
*
* When writing, data is typically stored in both the memory cache and the
* disk cache. Both the search order and this write policy can be modified by
* setting one or more of the flag argument bits, as defined above.
*
* The optionally-NULL secondaryKey argument can be used, e.g. for form
* post data or for HTTP headers in the case of HTTP.
*/
nsICachedNetData getCachedNetData(in string uri,
[size_is(secondaryKeyLength)] in string secondaryKey,
in PRUint32 secondaryKeyLength,
in PRUint32 flags);
/**
* Returns true if cached content is available for the given URI, even if
* only partial data is stored. The flags argument behaves the same as for
* the GetCachedNetData() method, above.
*/
boolean contains(in string uri,
[size_is(secondaryKeyLength)] in string secondaryKey,
in PRUint32 secondaryKeyLength,
in PRUint32 flags);
/**
* Total number of unexpired URI entries stored in all caches. This number
* does not take into account duplicate URIs, e.g. because the memory cache
* and the disk cache might each contain an entry for the same URI.
*/
readonly attribute PRUint32 numEntries;
/**
* Enumerate the unexpired URI entries stored in all caches. Some URIs may
* be enumerated more than once, e.g. because the the memory cache and the
* disk cache might each contain an entry for the same URI.
*/
nsISimpleEnumerator newCacheEntryIterator();
/*
* Enumerate all the loaded nsINetDataCache-implementing cache modules.
* The first module enumerated will be the memory cache, the second will be
* the disk cache, then the file cache, followed by all the extension
* caches, in search order.
*/
nsISimpleEnumerator newCacheModuleIterator();
/**
* Remove all entries from all writable caches. This could be used, for
* example, after a guest ends a browser session. This is equivalent to
* setting the DiskCacheCapacity to zero, except that all cache entries,
* even those in active use, will be deleted. Also, any global cache
* database files will be deleted.
*/
void RemoveAll();
/**
* The disk cache is made up of the file cache (for stream-as-file
* requests) and a (possibly independent) persistent cache that handles all
* other cache requests. This attribute sets/gets the combined capacity of
* these caches, measured in KBytes. Setting the capacity lower than the
* current amount of space currently in use may cause cache entries to be
* evicted from the cache to accomodate the requested capacity.
*/
attribute PRUint32 diskCacheCapacity;
/**
* This attribute sets/gets the capacity of the memory cache, measured in
* KBytes. Setting the capacity lower than the current amount of space
* currently in use may cause cache entries to be evicted from the cache to
* accomodate the requested capacity.
*/
attribute PRUint32 memCacheCapacity;
/**
* This attribute must be set before attempting to store into the disk cache.
*/
attribute nsIFileSpec diskCacheFolder;
};
%{ C++
// ProgID prefix for Components that implement this interface
#define NS_NETWORK_CACHE_MANAGER_PROGID NS_NETWORK_CACHE_PROGID "?name=manager"
%}

View File

@@ -0,0 +1,125 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsISupports.idl"
#include "nsrootidl.idl"
interface nsIFileSpec;
interface nsIChannel;
interface nsINetDataCache;
/**
* The nsINetDataCacheRecord represents a single entry in a database that
* caches data retrieved from the network. On top of this low-level interface
* to the raw record data, the cache manager implements a higher-level record
* interface, nsICachedNetData. Each instance of nsINetDataCacheRecord is
* (internally) associated with a parent database, an instance of the
* nsINetDataCache interface. This interface is essentially a pseudo-private
* API for the cache manager. Other clients should never use this interface.
*
* Each cache record may contain both content and metadata. The content may
* be, for example, GIF image data or HTML, and it is accessed through
* nsIChannel's streaming API. The opaque metadata, which may contain HTTP
* headers among other things, is accessed as a contiguous byte array. Each
* entry in the cache is indexed by two different keys: a unique record id
* number, generated by the cache, and an opaque string. The latter contains
* the URI and other secondary key information, e.g. HTTP form post key/value
* pairs.
*
* The nsINetDataCacheRecord interface is agnostic as to where the data is
* stored and whether the storage is volatile or persistent. The memory cache,
* the disk cache, a flat-file cache and any read-only extension caches must
* all implement this interface.
*
* @See nsICachedNetData
* @See nsINetDataCache
* @See nsINetDataDiskCache
* @See nsINetDataCacheManager
*/
interface nsILoadGroup;
[scriptable, uuid(fdcdd6a0-7461-11d3-90ca-0040056a906e)]
interface nsINetDataCacheRecord : nsISupports
{
/**
* As far as the nsINetDataCacheRecord implementation is concerned, the
* cache entry database key is an opaque blob, but it's intended to contain
* both the URI and any secondary keys, such as HTTP post data.
*/
void getKey(out unsigned long length, [size_is(length), retval] out string key);
/**
* A persistent record number assigned by the cache which must be unique
* among all entries stored within the same cache. The record ID serves as
* an alternate key to the cache record. Providing that they satisfy the
* afforementioned uniqueness requirement, record IDs can be assigned any
* value by the database except that they may never be zero.
*/
readonly attribute PRInt32 recordID;
/**
* Opaque data which can be updated for each cache entry independently of
* the content data. This data is a combination of protocol-independent
* data provided by the cache manager and protocol-specific meta-data,
* e.g. HTTP headers.
*/
void getMetaData(out PRUint32 length, [size_is(length), retval] out string metaData);
void setMetaData(in PRUint32 length, [size_is(length)] in string data);
/**
* Number of content bytes stored in the cache, i.e. via the nsIChannel
* streaming APIs. This may be less than the complete content length if a
* partial cache fill occurred. Additionally, the cached content can be
* truncated by reducing the value of this attribute. When this attribute
* is set to zero the associated cache disk file, if any, should be
* deleted.
*/
attribute PRUint32 storedContentLength;
/**
* Delete this cache entry and its associated content.
*/
void delete();
/**
* Create a channel for reading or writing a stream of content into the
* entry. However, many of the nsIChannel methods may return
* NS_NOT_IMPLEMENTED, including:
*
* + GetURI()
* + GetContentType()
* + GetContentLength()
*/
nsIChannel newChannel(in nsILoadGroup loadGroup);
/**
* If a cache is implemented such that it stores each URI's content in an
* individual disk file, this method will identify the file corresponding
* to this record. This may be used to implement the "stream-as-file"
* semantics required by some plugins and by the 'jar:' protocol handler.
* However, not all cache implementations are *required* to store the data
* from each URI in an individual file, so it is acceptable for an
* implementation of this method to signal NS_NOT_IMPLEMENTED.
*/
readonly attribute nsIFileSpec filename;
};

View File

@@ -0,0 +1,42 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsINetDataCache.idl"
interface nsIFileSpec;
/**
/**
* A network-data disk cache is used to persistently cache the responses to
* network retrieval commands. Each cache entry may contain both content,
* e.g. GIF image data, and associated metadata, e.g. HTTP headers.
*/
[scriptable, uuid(6408e390-6f13-11d3-90c8-000064657374)]
interface nsINetDataDiskCache : nsINetDataCache
{
/**
* This attribute must be set before calling any other methods of this
* interface.
*/
attribute nsIFileSpec diskCacheFolder;
};

View File

@@ -0,0 +1,106 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#include "nsrootidl.idl"
#include "nsISupports.idl"
interface nsIFileSpec;
interface nsIStreamAsFileObserver;
/**
* In addition to enhancing effective network response time via caching, the
* cache manager serves a second purpose by providing the stream-as-file
* service required by traditional browser plugins and the jar: protocol
* handler. The interface below provides a means for a client to determine the
* filename associated with a stream and to detect modification/deletion of
* that file.
*/
[scriptable, uuid(0eedbbf0-92d9-11d3-90d3-0040056a906e)]
interface nsIStreamAsFile : nsISupports
{
/**
* Filename containing stream-as-file
*/
readonly attribute nsIFileSpec fileSpec;
/**
* Add an observer for this cache record. When the cache wants to delete
* or truncate a record, so as to make space for another cache entry's
* content data, it will call <code>aObserver</code>'s Observe() method,
* passing the nsIStreamAsFile instance as the <code>aSubject</code>
* argument and an appropriate message. If the observer does not wish to
* inhibit deletion/truncation, it should Release() any references it has to the
* cache record.
*
* @See nsIStreamAsFileObserver
*/
void addObserver(in nsIStreamAsFileObserver aObserver);
/**
* Delete an observer that was added by the AddObserver() method.
*/
void removeObserver(in nsIStreamAsFileObserver aObserver);
};
/**
* This interface can be implemented by a client to receive notifications of
* either modification or deletion of a file created by the cache manager using
* the stream-as-file semantics.
*/
[scriptable, uuid(a26e27c0-92da-11d3-90d3-0040056a906e)]
interface nsIStreamAsFileObserver : nsISupports
{
/**
* Flag bits for argument to Observe() method.
*/
const long NOTIFY_AVAILABLE = 1 << 0; // Stream-as-file now available for reading
const long NOTIFY_ERROR = 1 << 1; // Error while loading stream / creating file
const long REQUEST_DELETION = 1 << 2; // Cache manager wishes to delete/truncate file
const long INVALIDATE = 1 << 3; // File is out-of-date
// Convenience value
const long MAKE_UNAVAILABLE = REQUEST_DELETION | INVALIDATE;
/**
* Receive either a notification or a request concerning a file that has
* been opened using stream-as-file. The aMessage and aError arguments
* have varying values depending on the nature of the notification.
* aMessage is set to NOTIFY_AVAILABLE when a complete stream has been read
* and stored on disk in a file. At that point, and no sooner, may the
* filename attribute of the associated nsIStreamAsFile be accessed via the
* associated nsIStreamAsFile interface. If the aMessage argument is
* NOTIFY_ERROR, the aError argument contains the relevant error code. If
* the aMessage argument is either REQUEST_DELETION or REQUEST_TRUNCATION,
* the callee should immediately Release() all references to the
* nsIStreamAsFile (and any references to its associated nsICachedNetData
* instances), unless it wishes to inhibit the requested file modification.
* If the aMessage argument is INVALIDATE, the cache manager is replacing
* the file with a more recent version. If a client wants to continue
* using the (now out-of-date) file, it must delete it when it has finished,
* as the cache manager will effectively relinquished ownership of the
* file.
*/
void ObserveStreamAsFile(in nsIStreamAsFile aStreamAsFile,
in PRUint32 aMessage,
in nsresult aError);
};

View File

@@ -0,0 +1,39 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH = ..
MODULE = necko
DIRS= \
base \
dns \
build \
protocol \
socket \
util \
mime \
streamconv \
cache \
test \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -0,0 +1,32 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsISupports.idl"
interface nsIAtom;
[scriptable, uuid(a3ec67f0-465a-11d3-9a89-0080c7cb1080)]
interface nsIHTTPHeader : nsISupports
{
nsIAtom GetField();
string GetValue();
};

View File

@@ -0,0 +1,603 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsIStreamListener.h"
#include "nsIStreamObserver.h"
#include "nsIServiceManager.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIEventQueue.h"
#include "nsIEventQueueService.h"
#include "nsIChannel.h"
#include "nsCOMPtr.h"
#include "nsINetDataCache.h"
#include "nsINetDataCacheManager.h"
#include "nsICachedNetData.h"
// Number of test entries to be placed in the cache
// FIXME - temporary
#define NUM_CACHE_ENTRIES 25
// Cache content stream length will have random length between zero and
// MAX_CONTENT_LENGTH bytes
#define MAX_CONTENT_LENGTH 20000
// Limits, converted to KB
#define DISK_CACHE_CAPACITY ((MAX_CONTENT_LENGTH * 4) >> 10)
#define MEM_CACHE_CAPACITY ((MAX_CONTENT_LENGTH * 3) >> 10)
// Length of random-data cache entry URI key
#define CACHE_KEY_LENGTH 13
// Length of random-data cache entry secondary key
#define CACHE_SECONDARY_KEY_LENGTH 10
// Length of random-data cache entry meta-data
#define CACHE_PROTOCOL_PRIVATE_LENGTH 10
// Mapping from test case number to RecordID
static PRInt32 recordID[NUM_CACHE_ENTRIES];
static PRInt32
mapRecordIdToTestNum(PRInt32 aRecordID)
{
int i;
for (i = 0; i < NUM_CACHE_ENTRIES; i++) {
if (recordID[i] == aRecordID)
return i;
}
return -1;
}
// A supply of stream data to either store or compare with
class nsITestDataStream {
public:
virtual ~nsITestDataStream() {};
virtual PRUint32 Next() = 0;
virtual void Read(char* aBuf, PRUint32 aCount) = 0;
virtual void ReadString(char* aBuf, PRUint32 aCount) = 0;
virtual PRBool Match(char* aBuf, PRUint32 aCount) = 0;
virtual PRBool MatchString(char* aBuf, PRUint32 aCount) = 0;
virtual void Skip(PRUint32 aCount) = 0;
virtual void SkipString(PRUint32 aCount) = 0;
};
// A reproducible stream of random data.
class RandomStream : public nsITestDataStream {
public:
RandomStream(PRUint32 aSeed) {
mStartSeed = mState = aSeed;
}
PRUint32 GetStartSeed() {
return mStartSeed;
}
PRUint32 Next() {
mState = 1103515245 * mState + 12345 ^ (mState >> 16);
return mState;
}
PRUint8 NextChar() {
PRUint8 c;
do {
c = Next();
} while (!isalnum(c));
return c;
}
void Read(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
*aBuf++ = Next();
}
}
// Same as Read(), but using only printable chars and
// with a terminating NUL
void ReadString(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
*aBuf++ = NextChar();
}
*aBuf = 0;
}
PRBool
Match(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
if (*aBuf++ != (char)(Next() & 0xff))
return PR_FALSE;
}
return PR_TRUE;
}
PRBool
MatchString(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
if (*aBuf++ != (char)(NextChar() & 0xff))
return PR_FALSE;
}
// Check for terminating NUL character
if (*aBuf)
return PR_FALSE;
return PR_TRUE;
}
void
Skip(PRUint32 aCount) {
while (aCount--)
Next();
}
void
SkipString(PRUint32 aCount) {
while (aCount--)
NextChar();
}
protected:
PRUint32 mState;
PRUint32 mStartSeed;
};
static int gNumReaders = 0;
static PRUint32 gTotalBytesRead = 0;
static PRUint32 gTotalBytesWritten = 0;
static PRUint32 gTotalDuration = 0;
class nsReader : public nsIStreamListener {
public:
NS_DECL_ISUPPORTS
nsReader()
: mStartTime(0), mBytesRead(0)
{
NS_INIT_REFCNT();
gNumReaders++;
}
virtual ~nsReader() {
delete mTestDataStream;
gNumReaders--;
}
nsresult
Init(nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
mTestDataStream = aRandomStream;
mExpectedStreamLength = aExpectedStreamLength;
mRefCnt = 1;
return NS_OK;
}
NS_IMETHOD OnStartRequest(nsIChannel* channel,
nsISupports* context) {
mStartTime = PR_IntervalNow();
return NS_OK;
}
NS_IMETHOD OnDataAvailable(nsIChannel* channel,
nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength) {
char buf[1025];
while (aLength > 0) {
PRUint32 amt;
PRBool match;
aIStream->Read(buf, sizeof buf, &amt);
if (amt == 0) break;
aLength -= amt;
mBytesRead += amt;
match = mTestDataStream->Match(buf, amt);
NS_ASSERTION(match, "Stored data was corrupted on read");
}
return NS_OK;
}
NS_IMETHOD OnStopRequest(nsIChannel* channel,
nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg) {
PRIntervalTime endTime;
PRIntervalTime duration;
endTime = PR_IntervalNow();
duration = (endTime - mStartTime);
if (NS_FAILED(aStatus)) printf("channel failed.\n");
// printf("read %d bytes\n", mBytesRead);
//FIXME NS_ASSERTION(mBytesRead == mExpectedStreamLength,
// "Stream in cache is wrong length");
gTotalBytesRead += mBytesRead;
gTotalDuration += duration;
return NS_OK;
}
protected:
PRIntervalTime mStartTime;
PRUint32 mBytesRead;
nsITestDataStream* mTestDataStream;
PRUint32 mExpectedStreamLength;
};
NS_IMPL_ISUPPORTS2(nsReader, nsIStreamListener, nsIStreamObserver)
static nsIEventQueue* eventQueue;
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
nsresult
InitQueue() {
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue service");
rv = eventQService->CreateThreadEventQueue();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create event queue");
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQueue);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue for main thread");
return NS_OK;
}
// Process events until all streams are OnStopRequest'ed
nsresult
WaitForEvents() {
while (gNumReaders) {
eventQueue->ProcessPendingEvents();
}
return NS_OK;
}
// Read data for a single cache record and compare against testDataStream
nsresult
TestReadStream(nsICachedNetData *cacheEntry, nsITestDataStream *testDataStream,
PRUint32 expectedStreamLength)
{
nsCOMPtr<nsIChannel> channel;
nsresult rv;
PRUint32 actualContentLength;
rv = cacheEntry->NewChannel(0, 0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = cacheEntry->GetStoredContentLength(&actualContentLength);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
// FIXME NS_ASSERTION(actualContentLength == expectedStreamLength,
// "nsICachedNetData::GetContentLength() busted ?");
nsReader *reader = new nsReader;
reader->AddRef();
rv = reader->Init(testDataStream, expectedStreamLength);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = channel->AsyncRead(0, -1, 0, reader);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
reader->Release();
return NS_OK;
}
// Convert PRTime to unix-style time_t, i.e. seconds since the epoch
static PRUint32
convertPRTimeToSeconds(PRTime aTime64)
{
double fpTime;
LL_L2D(fpTime, aTime64);
return (PRUint32)(fpTime * 1e-6 + 0.5);
}
// Convert unix-style time_t, i.e. seconds since the epoch, to PRTime
static PRTime
convertSecondsToPRTime(PRUint32 aSeconds)
{
PRInt64 t64;
LL_L2I(t64, aSeconds);
LL_MUL(t64, t64, 1000000);
return t64;
}
// Read the test data that was written in FillCache(), checking for
// corruption, truncation.
nsresult
TestRead(nsINetDataCacheManager *aCache, PRUint32 aFlags)
{
nsresult rv;
PRBool inCache;
nsCOMPtr<nsICachedNetData> cacheEntry;
RandomStream *randomStream;
char uriCacheKey[CACHE_KEY_LENGTH];
char secondaryCacheKey[CACHE_SECONDARY_KEY_LENGTH];
char *storedUriKey;
PRUint32 testNum;
gTotalBytesRead = 0;
gTotalDuration = 0;
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->ReadString(uriCacheKey, sizeof uriCacheKey - 1);
randomStream->Read(secondaryCacheKey, sizeof secondaryCacheKey);
// Ensure that entry is in the cache
rv = aCache->Contains(uriCacheKey,
secondaryCacheKey, sizeof secondaryCacheKey,
aFlags, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(inCache, "nsINetDataCacheManager::Contains error");
rv = aCache->GetCachedNetData(uriCacheKey,
secondaryCacheKey, sizeof secondaryCacheKey,
aFlags,
getter_AddRefs(cacheEntry));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
// Test GetUriSpec() method
rv = cacheEntry->GetUriSpec(&storedUriKey);
NS_ASSERTION(NS_SUCCEEDED(rv) &&
!memcmp(storedUriKey, &uriCacheKey[0], sizeof uriCacheKey),
"nsICachedNetData::GetKey failed");
nsAllocator::Free(storedUriKey);
// Test GetSecondaryKey() method
PRUint32 storedSecondaryKeyLength;
char* storedSecondaryKey;
rv = cacheEntry->GetSecondaryKey(&storedSecondaryKeyLength, &storedSecondaryKey);
NS_ASSERTION(NS_SUCCEEDED(rv) &&
!memcmp(storedSecondaryKey, &secondaryCacheKey[0],
sizeof secondaryCacheKey),
"nsICachedNetData::GetSecondaryKey failed");
// Compare against stored protocol data
char *storedProtocolData;
PRUint32 storedProtocolDataLength;
rv = cacheEntry->GetAnnotation("test data", &storedProtocolDataLength, &storedProtocolData);
NS_ASSERTION(NS_SUCCEEDED(rv) &&
storedProtocolDataLength == CACHE_PROTOCOL_PRIVATE_LENGTH,
"nsICachedNetData::GetAnnotation() failed");
randomStream->Match(storedProtocolData, storedProtocolDataLength);
// Test GetAllowPartial()
PRBool allowPartial;
rv = cacheEntry->GetAllowPartial(&allowPartial);
NS_ASSERTION(NS_SUCCEEDED(rv) &&
(allowPartial == (PRBool)(randomStream->Next() & 1)),
"nsICachedNetData::GetAllowPartial() failed");
// Test GetExpirationTime()
PRTime expirationTime;
PRTime expectedExpirationTime = convertSecondsToPRTime(randomStream->Next() & 0xffffff);
rv = cacheEntry->GetExpirationTime(&expirationTime);
NS_ASSERTION(NS_SUCCEEDED(rv) && LL_EQ(expirationTime, expectedExpirationTime),
"nsICachedNetData::GetExpirationTime() failed");
PRUint32 expectedStreamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
TestReadStream(cacheEntry, randomStream, expectedStreamLength);
}
WaitForEvents();
// Compute rate in MB/s
double rate = gTotalBytesRead / PR_IntervalToMilliseconds(gTotalDuration);
rate *= NUM_CACHE_ENTRIES;
rate *= 1000;
rate /= (1024 * 1024);
printf("Read %7d bytes at a rate of %5.1f MB per second \n",
gTotalBytesRead, rate);
return NS_OK;
}
// Create entries in the network data cache, using random data for the
// key, the meta-data and the stored content data.
nsresult
FillCache(nsINetDataCacheManager *aCache, PRUint32 aFlags, PRUint32 aCacheCapacity)
{
nsresult rv;
PRBool inCache;
nsCOMPtr<nsICachedNetData> cacheEntry;
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIOutputStream> outStream;
nsCOMPtr<nsINetDataCache> containingCache;
char buf[1000];
PRUint32 protocolDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char secondaryCacheKey[CACHE_SECONDARY_KEY_LENGTH];
char protocolData[CACHE_PROTOCOL_PRIVATE_LENGTH];
PRUint32 testNum;
RandomStream *randomStream;
gTotalBytesWritten = 0;
PRIntervalTime startTime = PR_IntervalNow();
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->ReadString(cacheKey, sizeof cacheKey - 1);
randomStream->Read(secondaryCacheKey, sizeof secondaryCacheKey);
// No entry should be in cache until we add it
rv = aCache->Contains(cacheKey,
secondaryCacheKey, sizeof secondaryCacheKey,
aFlags, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(!inCache, "nsINetDataCacheManager::Contains error");
rv = aCache->GetCachedNetData(cacheKey,
secondaryCacheKey, sizeof secondaryCacheKey,
aFlags,
getter_AddRefs(cacheEntry));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access cacheEntry via cache key");
// Test nsINetDataCacheManager::GetNumEntries()
PRUint32 numEntries = (PRUint32)-1;
rv = aCache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == testNum + 1, "GetNumEntries failure");
// Record meta-data should be initially empty
char *protocolDatap;
rv = cacheEntry->GetAnnotation("test data", &protocolDataLength, &protocolDatap);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
if ((protocolDataLength != 0) || (protocolDatap != 0))
return NS_ERROR_FAILURE;
// Store random data as meta-data
randomStream->Read(protocolData, sizeof protocolData);
cacheEntry->SetAnnotation("test data", sizeof protocolData, protocolData);
// Store random data as allow-partial flag
PRBool allowPartial = randomStream->Next() & 1;
rv = cacheEntry->SetAllowPartial(allowPartial);
NS_ASSERTION(NS_SUCCEEDED(rv),
"nsICachedNetData::SetAllowPartial() failed");
// Store random data as expiration time
PRTime expirationTime = convertSecondsToPRTime(randomStream->Next() & 0xffffff);
rv = cacheEntry->SetExpirationTime(expirationTime);
NS_ASSERTION(NS_SUCCEEDED(rv),
"nsICachedNetData::SetExpirationTime() failed");
// Cache manager complains if expiration set without setting last-modified time
rv = cacheEntry->SetLastModifiedTime(expirationTime);
rv = cacheEntry->NewChannel(0, 0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = cacheEntry->GetCache(getter_AddRefs(containingCache));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = channel->OpenOutputStream(0, getter_AddRefs(outStream));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
int streamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
int remaining = streamLength;
while (remaining) {
PRUint32 numWritten;
int amount = PR_MIN(sizeof buf, remaining);
randomStream->Read(buf, amount);
rv = outStream->Write(buf, amount, &numWritten);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(numWritten == (PRUint32)amount, "Write() bug?");
remaining -= amount;
PRUint32 storageInUse;
rv = containingCache->GetStorageInUse(&storageInUse);
NS_ASSERTION(NS_SUCCEEDED(rv) && (storageInUse <= aCacheCapacity),
"Cache manager failed to limit cache growth");
}
outStream->Close();
gTotalBytesWritten += streamLength;
// *Now* there should be an entry in the cache
rv = aCache->Contains(cacheKey,
secondaryCacheKey, sizeof secondaryCacheKey,
aFlags, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(inCache, "nsINetDataCacheManager::Contains error");
delete randomStream;
}
PRIntervalTime endTime = PR_IntervalNow();
// Compute rate in MB/s
double rate = gTotalBytesWritten / PR_IntervalToMilliseconds(endTime - startTime);
rate *= 1000;
rate /= (1024 * 1024);
printf("Wrote %7d bytes at a rate of %5.1f MB per second \n",
gTotalBytesWritten, rate);
return NS_OK;
}
nsresult NS_AutoregisterComponents()
{
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
NULL /* default */);
return rv;
}
nsresult
Test(nsINetDataCacheManager *aCache, PRUint32 aFlags, PRUint32 aCacheCapacity)
{
nsresult rv;
rv = aCache->RemoveAll();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
PRUint32 numEntries = (PRUint32)-1;
rv = aCache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
rv = FillCache(aCache, aFlags, aCacheCapacity);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't fill cache with random test data");
rv = TestRead(aCache, aFlags);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't read random test data from cache");
rv = aCache->RemoveAll();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
rv = aCache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
return 0;
}
int
main(int argc, char* argv[])
{
nsresult rv;
nsCOMPtr<nsINetDataCacheManager> cache;
rv = NS_AutoregisterComponents();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
rv = nsComponentManager::CreateInstance(NS_NETWORK_CACHE_MANAGER_PROGID,
nsnull,
NS_GET_IID(nsINetDataCacheManager),
getter_AddRefs(cache));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create cache manager factory") ;
cache->SetDiskCacheCapacity(DISK_CACHE_CAPACITY);
cache->SetMemCacheCapacity(MEM_CACHE_CAPACITY);
InitQueue();
Test(cache, nsINetDataCacheManager::BYPASS_PERSISTENT_CACHE, MEM_CACHE_CAPACITY);
Test(cache, nsINetDataCacheManager::BYPASS_MEMORY_CACHE, DISK_CACHE_CAPACITY);
return 0;
}

View File

@@ -0,0 +1,820 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsIStreamListener.h"
#include "nsIStreamObserver.h"
#include "nsIServiceManager.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIEventQueue.h"
#include "nsIEventQueueService.h"
#include "nsIChannel.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include <stdio.h>
#include "nsINetDataCache.h"
#include "nsINetDataDiskCache.h"
#include "nsINetDataCacheRecord.h"
#include "nsMemCacheCID.h"
// file cache include
#include "nsNetDiskCacheCID.h"
#include "nsIPref.h"
#include "prenv.h"
#include "nsIFileStream.h"
// Number of test entries to be placed in the cache
#define NUM_CACHE_ENTRIES 250
// Cache content stream length will have random length between zero and
// MAX_CONTENT_LENGTH bytes
#define MAX_CONTENT_LENGTH 20000
// Length of random-data cache entry key
#define CACHE_KEY_LENGTH 15
// Length of random-data cache entry meta-data
#define CACHE_METADATA_LENGTH 100
static NS_DEFINE_CID(kMemCacheCID, NS_MEM_CACHE_FACTORY_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
// file cache cid
static NS_DEFINE_CID(kDiskCacheCID, NS_NETDISKCACHE_CID) ;
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
static NS_DEFINE_IID(kIPrefIID, NS_IPREF_IID);
// Mapping from test case number to RecordID
static PRInt32 recordID[NUM_CACHE_ENTRIES];
static PRInt32
mapRecordIdToTestNum(PRInt32 aRecordID)
{
int i;
for (i = 0; i < NUM_CACHE_ENTRIES; i++) {
if (recordID[i] == aRecordID)
return i;
}
return -1;
}
// A supply of stream data to either store or compare with
class nsITestDataStream {
public:
virtual ~nsITestDataStream() {};
virtual PRUint32 Next() = 0;
virtual void Read(char* aBuf, PRUint32 aCount) = 0;
virtual PRBool Match(char* aBuf, PRUint32 aCount) = 0;
virtual void Skip(PRUint32 aCount) = 0;
};
// A reproducible stream of random data.
class RandomStream : public nsITestDataStream {
public:
RandomStream(PRUint32 aSeed) {
mStartSeed = mState = aSeed;
}
PRUint32 GetStartSeed() {
return mStartSeed;
}
PRUint32 Next() {
mState = 1103515245 * mState + 12345;
return mState;
}
void Read(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
*aBuf++ = Next();
}
}
PRBool
Match(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
if (*aBuf++ != (char)(Next() & 0xff))
return PR_FALSE;
}
return PR_TRUE;
}
void
Skip(PRUint32 aCount) {
while (aCount--)
Next();
}
protected:
PRUint32 mState;
PRUint32 mStartSeed;
};
// A stream of data that increments on each byte that is read, modulo 256
class CounterStream : public nsITestDataStream {
public:
CounterStream(PRUint32 aSeed) {
mStartSeed = mState = aSeed;
}
PRUint32 GetStartSeed() {
return mStartSeed;
}
PRUint32 Next() {
mState += 1;
mState &= 0xff;
return mState;
}
void Read(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
*aBuf++ = Next();
}
}
PRBool
Match(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
if (*aBuf++ != (char)Next())
return PR_FALSE;
}
return PR_TRUE;
}
void
Skip(PRUint32 aCount) {
mState += aCount;
mState &= 0xff;
}
protected:
PRUint32 mState;
PRUint32 mStartSeed;
};
static int gNumReaders = 0;
static PRUint32 gTotalBytesRead = 0;
static PRUint32 gTotalDuration = 0;
class nsReader : public nsIStreamListener {
public:
NS_DECL_ISUPPORTS
nsReader()
: mStartTime(0), mBytesRead(0)
{
NS_INIT_REFCNT();
gNumReaders++;
}
virtual ~nsReader() {
delete mTestDataStream;
gNumReaders--;
}
nsresult
Init(nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
mTestDataStream = aRandomStream;
mExpectedStreamLength = aExpectedStreamLength;
mRefCnt = 1;
return NS_OK;
}
NS_IMETHOD OnStartRequest(nsIChannel* channel,
nsISupports* context) {
mStartTime = PR_IntervalNow();
return NS_OK;
}
NS_IMETHOD OnDataAvailable(nsIChannel* channel,
nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength) {
char buf[1025];
while (aLength > 0) {
PRUint32 amt;
PRBool match;
aIStream->Read(buf, sizeof buf, &amt);
if (amt == 0) break;
aLength -= amt;
mBytesRead += amt;
match = mTestDataStream->Match(buf, amt);
NS_ASSERTION(match, "Stored data was corrupted on read");
}
return NS_OK;
}
NS_IMETHOD OnStopRequest(nsIChannel* channel,
nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg) {
PRIntervalTime endTime;
PRIntervalTime duration;
endTime = PR_IntervalNow();
duration = (endTime - mStartTime);
if (NS_FAILED(aStatus)) printf("channel failed.\n");
// printf("read %d bytes\n", mBytesRead);
NS_ASSERTION(mBytesRead == mExpectedStreamLength,
"Stream in cache is wrong length");
gTotalBytesRead += mBytesRead;
gTotalDuration += duration;
return NS_OK;
}
protected:
PRIntervalTime mStartTime;
PRUint32 mBytesRead;
nsITestDataStream* mTestDataStream;
PRUint32 mExpectedStreamLength;
};
NS_IMPL_ISUPPORTS2(nsReader, nsIStreamListener, nsIStreamObserver)
static nsIEventQueue* eventQueue;
nsresult
InitQueue() {
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue service");
rv = eventQService->CreateThreadEventQueue();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create event queue");
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQueue);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue for main thread");
return NS_OK;
}
// Process events until all streams are OnStopRequest'ed
nsresult
WaitForEvents() {
while (gNumReaders) {
eventQueue->ProcessPendingEvents();
}
return NS_OK;
}
// Read data for a single cache record and compare against testDataStream
nsresult
TestReadStream(nsINetDataCacheRecord *record, nsITestDataStream *testDataStream,
PRUint32 expectedStreamLength)
{
nsCOMPtr<nsIChannel> channel;
nsresult rv;
PRUint32 actualContentLength;
rv = record->NewChannel(0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = record->GetStoredContentLength(&actualContentLength);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(actualContentLength == expectedStreamLength,
"nsINetDataCacheRecord::GetContentLength() busted ?");
nsReader *reader = new nsReader;
rv = reader->Init(testDataStream, expectedStreamLength);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = channel->AsyncRead(0, -1, 0, reader);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
reader->Release();
return NS_OK;
}
// Check that records can be retrieved using their record-ID, in addition
// to using the opaque key.
nsresult
TestRecordID(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
RandomStream *randomStream;
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char *metaData;
PRUint32 testNum;
PRBool match;
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
rv = cache->GetCachedNetDataByID(recordID[testNum], getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't obtain record using record ID");
// Match against previously stored meta-data
rv = record->GetMetaData(&metaDataLength, &metaData);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
match = randomStream->Match(metaData, metaDataLength);
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
nsAllocator::Free(metaData);
delete randomStream;
}
return NS_OK;
}
// Check that all cache entries in the database are enumerated and that
// no duplicates appear.
nsresult
TestEnumeration(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
nsCOMPtr<nsISupports> tempISupports;
nsCOMPtr<nsISimpleEnumerator> iterator;
RandomStream *randomStream;
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char *metaData;
PRUint32 testNum;
PRBool match;
PRInt32 recID;
int numRecords = 0;
// Iterate over all records in the cache
rv = cache->NewCacheEntryIterator(getter_AddRefs(iterator));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create new cache entry iterator");
PRBool notDone;
while (1) {
// Done iterating ?
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
// Get next record in iteration
rv = iterator->GetNext(getter_AddRefs(tempISupports));
NS_ASSERTION(NS_SUCCEEDED(rv), "iterator bustage");
record = do_QueryInterface(tempISupports);
numRecords++;
// Get record ID
rv = record->GetRecordID(&recID);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
testNum = mapRecordIdToTestNum(recID);
NS_ASSERTION(testNum != -1, "Corrupted Record ID ?");
// Erase mapping from table, so that duplicate enumerations are detected
recordID[testNum] = -1;
// Make sure stream matches test data
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
// Match against previously stored meta-data
rv = record->GetMetaData(&metaDataLength, &metaData);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
match = randomStream->Match(metaData, metaDataLength);
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
nsAllocator::Free(metaData);
delete randomStream;
}
NS_ASSERTION(numRecords == NUM_CACHE_ENTRIES, "Iteration bug");
return NS_OK;
}
// Read the test data that was written in FillCache(), checking for
// corruption, truncation.
nsresult
TestRead(nsINetDataCache *cache)
{
nsresult rv;
PRBool inCache;
nsCOMPtr<nsINetDataCacheRecord> record;
RandomStream *randomStream;
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char *metaData, *storedCacheKey;
PRUint32 testNum, storedCacheKeyLength;
PRBool match;
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
// Ensure that entry is in the cache
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
// Match against previously stored meta-data
match = record->GetMetaData(&metaDataLength, &metaData);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
match = randomStream->Match(metaData, metaDataLength);
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
nsAllocator::Free(metaData);
// Test GetKey() method
rv = record->GetKey(&storedCacheKeyLength, &storedCacheKey);
NS_ASSERTION(NS_SUCCEEDED(rv) &&
(storedCacheKeyLength == sizeof cacheKey) &&
!memcmp(storedCacheKey, &cacheKey[0], sizeof cacheKey),
"nsINetDataCacheRecord::GetKey failed");
nsAllocator::Free(storedCacheKey);
PRUint32 expectedStreamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
TestReadStream(record, randomStream, expectedStreamLength);
}
WaitForEvents();
// Compute rate in MB/s
double rate = gTotalBytesRead / PR_IntervalToMilliseconds(gTotalDuration);
rate *= NUM_CACHE_ENTRIES;
rate *= 1000;
rate /= (1024 * 1024);
printf("Read %d bytes at a rate of %5.1f MB per second \n",
gTotalBytesRead, rate);
return NS_OK;
}
// Repeatedly call SetStoredContentLength() on a cache entry and make
// read the stream's data to ensure that it's not corrupted by the effect
nsresult
TestTruncation(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
RandomStream *randomStream;
char cacheKey[CACHE_KEY_LENGTH];
randomStream = new RandomStream(0);
randomStream->Read(cacheKey, sizeof cacheKey);
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
randomStream->Skip(CACHE_METADATA_LENGTH);
PRUint32 initialStreamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
delete randomStream;
PRUint32 i;
PRUint32 delta = initialStreamLength / 64;
for (i = initialStreamLength; i >= delta; i -= delta) {
PRUint32 expectedStreamLength = i;
// Do the truncation
record->SetStoredContentLength(expectedStreamLength);
randomStream = new RandomStream(0);
randomStream->Skip(CACHE_KEY_LENGTH + CACHE_METADATA_LENGTH + 1);
PRUint32 afterContentLength;
rv = record->GetStoredContentLength(&afterContentLength);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(afterContentLength == expectedStreamLength,
"nsINetDataCacheRecord::SetContentLength() failed to truncate record");
TestReadStream(record, randomStream, expectedStreamLength);
WaitForEvents();
}
return NS_OK;
}
// Write known data to random offsets in a single cache entry and test
// resulting stream for correctness.
nsresult
TestOffsetWrites(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIOutputStream> outStream;
char buf[512];
char cacheKey[CACHE_KEY_LENGTH];
RandomStream *randomStream;
randomStream = new RandomStream(0);
randomStream->Read(cacheKey, sizeof cacheKey);
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
// Write buffer-fulls of data at random offsets into the cache entry.
// Data written is (offset % 0xff)
PRUint32 startingOffset;
PRUint32 streamLength = 0;
CounterStream *counterStream;
int i;
for (i = 0; i < 100; i++) {
rv = record->NewChannel(0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
startingOffset = streamLength ? streamLength - (randomStream->Next() % sizeof buf): 0;
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
counterStream = new CounterStream(startingOffset);
counterStream->Read(buf, sizeof buf);
PRUint32 numWritten;
rv = outStream->Write(buf, sizeof buf, &numWritten);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
streamLength = startingOffset + sizeof buf;
rv = outStream->Close();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
delete counterStream;
}
delete randomStream;
counterStream = new CounterStream(0);
TestReadStream(record, counterStream, streamLength);
WaitForEvents();
return NS_OK;
}
// Create entries in the network data cache, using random data for the
// key, the meta-data and the stored content data.
nsresult
FillCache(nsINetDataCache *cache)
{
nsresult rv;
PRBool inCache;
nsCOMPtr<nsINetDataCacheRecord> record;
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIOutputStream> outStream;
char buf[1000];
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char metaData[CACHE_METADATA_LENGTH];
PRUint32 testNum;
char *data;
RandomStream *randomStream;
PRUint32 totalBytesWritten = 0;
PRIntervalTime startTime = PR_IntervalNow();
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
// No entry should be in cache until we add it
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(!inCache, "nsINetDataCache::Contains error");
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
// Test nsINetDataCacheRecord::GetRecordID()
rv = record->GetRecordID(&recordID[testNum]);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
// Test nsINetDataCache::GetNumEntries()
PRUint32 numEntries = (PRUint32)-1;
rv = cache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == testNum + 1, "GetNumEntries failure");
// Record meta-data should be initially empty
rv = record->GetMetaData(&metaDataLength, &data);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
if ((metaDataLength != 0) || (data != 0))
return NS_ERROR_FAILURE;
// Store random data as meta-data
randomStream->Read(metaData, sizeof metaData);
record->SetMetaData(sizeof metaData, metaData);
rv = record->NewChannel(0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = channel->OpenOutputStream(0, getter_AddRefs(outStream));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
PRUint32 beforeOccupancy;
rv = cache->GetStorageInUse(&beforeOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
int streamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
int remaining = streamLength;
while (remaining) {
PRUint32 numWritten;
int amount = PR_MIN(sizeof buf, remaining);
randomStream->Read(buf, amount);
rv = outStream->Write(buf, amount, &numWritten);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(numWritten == (PRUint32)amount, "Write() bug?");
remaining -= amount;
}
outStream->Close();
totalBytesWritten += streamLength;
PRUint32 afterOccupancy;
rv = cache->GetStorageInUse(&afterOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
PRUint32 streamLengthInKB = streamLength >> 10;
NS_ASSERTION((afterOccupancy - beforeOccupancy) >= streamLengthInKB,
"nsINetDataCache::GetStorageInUse() is busted");
// *Now* there should be an entry in the cache
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
delete randomStream;
}
PRIntervalTime endTime = PR_IntervalNow();
// Compute rate in MB/s
double rate = totalBytesWritten / PR_IntervalToMilliseconds(endTime - startTime);
rate *= 1000;
rate /= (1024 * 1024);
printf("Wrote %7d bytes at a rate of %5.1f MB per second \n",
totalBytesWritten, rate);
return NS_OK;
}
nsresult NS_AutoregisterComponents()
{
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
NULL /* default */);
return rv;
}
PRBool initPref ()
{
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefPtr, kPrefCID, &rv);
if (NS_FAILED(rv))
return false;
nsCOMPtr<nsIFileSpec> fileSpec;
rv = NS_NewFileSpec (getter_AddRefs(fileSpec));
if (NS_FAILED(rv))
return false;
nsCString defaultPrefFile = PR_GetEnv ("MOZILLA_FIVE_HOME");
if (defaultPrefFile.Length())
defaultPrefFile += "/";
else
defaultPrefFile = "./";
defaultPrefFile += "default_prefs.js";
fileSpec->SetUnixStyleFilePath (defaultPrefFile.GetBuffer());
PRBool exists = false;
fileSpec->Exists(&exists);
if (exists)
prefPtr->ReadUserPrefsFrom(fileSpec);
else
return false;
return true;
}
int
main(int argc, char* argv[])
{
nsresult rv;
if(argc <2) {
printf(" %s -f to test filecache\n", argv[0]) ;
printf(" %s -m to test memcache\n", argv[0]) ;
return -1 ;
}
rv = NS_AutoregisterComponents();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
nsCOMPtr<nsINetDataCache> cache;
if (PL_strcasecmp(argv[1], "-m") == 0) {
rv = nsComponentManager::CreateInstance(kMemCacheCID, nsnull,
NS_GET_IID(nsINetDataCache),
getter_AddRefs(cache));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create memory cache factory");
} else if (PL_strcasecmp(argv[1], "-f") == 0) {
nsCOMPtr<nsINetDataDiskCache> diskcache ;
rv = nsComponentManager::CreateInstance(kDiskCacheCID, nsnull,
NS_GET_IID(nsINetDataDiskCache),
getter_AddRefs(diskcache));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create disk cache factory") ;
nsCOMPtr<nsIFileSpec> folder ;
NS_NewFileSpec(getter_AddRefs(folder)) ;
folder->SetUnixStyleFilePath("/tmp") ;
diskcache->SetDiskCacheFolder(folder) ;
cache = diskcache ;
} else {
printf(" %s -f to test filecache\n", argv[0]) ;
printf(" %s -m to test memcache\n", argv[0]) ;
return -1 ;
}
InitQueue();
PRUnichar* description;
rv = cache->GetDescription(&description);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache description");
nsCAutoString descStr(description);
printf("Testing: %s\n", descStr.GetBuffer());
rv = cache->RemoveAll();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
PRUint32 startOccupancy;
rv = cache->GetStorageInUse(&startOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
PRUint32 numEntries = (PRUint32)-1;
rv = cache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
rv = FillCache(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't fill cache with random test data");
rv = TestRead(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't read random test data from cache");
rv = TestRecordID(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't index records using record ID");
rv = TestEnumeration(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully enumerate records");
rv = TestTruncation(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully truncate records");
rv = TestOffsetWrites(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully write to records using non-zero offsets");
rv = cache->RemoveAll();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
rv = cache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
PRUint32 endOccupancy;
rv = cache->GetStorageInUse(&endOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
NS_ASSERTION(startOccupancy == endOccupancy, "Cache occupancy not correctly computed ?");
return 0;
}

View File

@@ -0,0 +1,82 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..
MAKE_OBJ_TYPE = EXE
PROG1 = .\$(OBJDIR)\TestFileInput.exe
PROG2 = .\$(OBJDIR)\TestSocketInput.exe
PROG3 = .\$(OBJDIR)\TestSocketIO.exe
PROG4 = .\$(OBJDIR)\TestProtocols.exe
PROG5 = .\$(OBJDIR)\TestSocketTransport.exe
PROG6 = .\$(OBJDIR)\urltest.exe
PROG7 = .\$(OBJDIR)\TestFileInput2.exe
PROG8 = .\$(OBJDIR)\TestFileTransport.exe
PROG9 = .\$(OBJDIR)\TestRes.exe
PROGA = .\$(OBJDIR)\TestRawCache.exe
PROGB = .\$(OBJDIR)\TestCacheMgr.exe
PROGRAMS = \
#$(PROG1) $(PROG2) $(PROG3) $(PROG4) $(PROG5) $(PROG6) $(PROG7) $(PROG8) $(PROG9)\
$(PROGA) $(PROGB)
LCFLAGS=-DUSE_NSREG -GX
REQUIRES=libreg
INCS = $(INCS) \
-I$(DEPTH)\dist\include \
$(NULL)
LLIBS= \
$(DIST)\lib\xpcom.lib \
$(LIBNSPR) \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(PROGRAMS)
-for %p in ($(PROGRAMS)) do $(MAKE_INSTALL) %p $(DIST)\bin
clobber::
-for %p in ($(PROGRAMS)) do $(RM) %p $(DIST)\bin\%p
$(PROG1): $(OBJDIR) TestFileInput.cpp
$(PROG2): $(OBJDIR) TestSocketInput.cpp
$(PROG3): $(OBJDIR) TestSocketIO.cpp
$(PROG4): $(OBJDIR) TestProtocols.cpp
$(PROG5): $(OBJDIR) TestSocketTransport.cpp
$(PROG6): $(OBJDIR) urltest.cpp
$(PROG7): $(OBJDIR) TestFileInput2.cpp
$(PROG8): $(OBJDIR) TestFileTransport.cpp
$(PROG9): $(OBJDIR) TestRes.cpp
$(PROGA): $(OBJDIR) TestRawCache.cpp
$(PROGB): $(OBJDIR) TestCacheMgr.cpp

View File

@@ -1,80 +0,0 @@
#! gmake
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape security libraries.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1994-2000
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
include config.mk
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
export:: private_export

View File

@@ -1,82 +0,0 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape security libraries.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1994-2000
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
ifdef NISCC_TEST
DEFINES += -DNISCC_TEST
endif
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
# don't want the 32 in the shared library name
SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
IMPORT_LIBRARY = $(OBJDIR)/$(IMPORT_LIB_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION)$(IMPORT_LIB_SUFFIX)
RES = $(OBJDIR)/$(LIBRARY_NAME).res
RESNAME = $(LIBRARY_NAME).rc
ifdef NS_USE_GCC
EXTRA_SHARED_LIBS += \
-L$(DIST)/lib \
-lsqlite3 \
$(NULL)
else # ! NS_USE_GCC
EXTRA_SHARED_LIBS += \
$(DIST)/lib/sqlite3.lib \
$(NULL)
endif # NS_USE_GCC
else
# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
EXTRA_SHARED_LIBS += \
-L$(DIST)/lib/ \
-lsqlite3 \
$(NULL)
ifeq ($(OS_ARCH), BeOS)
EXTRA_SHARED_LIBS += -lbe
endif
ifeq ($(OS_TARGET),SunOS)
# The -R '$ORIGIN' linker option instructs this library to search for its
# dependencies in the same directory where it resides.
MKSHLIB += -R '$$ORIGIN'
endif
endif

View File

@@ -1,49 +0,0 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Red Hat, Inc.
#
# The Initial Developer of the Original Code is
# Red Hat, Inc.
# Portions created by the Initial Developer are Copyright (C) 2005
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
CORE_DEPTH = ../../..
MODULE = rdb
MAPFILE = $(OBJDIR)/rdb.def
CSRCS = \
rdb.c \
$(NULL)
REQUIRES = dbm nss sqlite nspr
LIBRARY_NAME = rdb

View File

@@ -1,807 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Red Hat, Inc.
*
* The Initial Developer of the Original Code is
* Red Hat, Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert Relyea (rrelyea@redhat.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* This file implements PKCS 11 on top of our existing security modules
*
* For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
* This implementation has two slots:
* slot 1 is our generic crypto support. It does not require login.
* It supports Public Key ops, and all they bulk ciphers and hashes.
* It can also support Private Key ops for imported Private keys. It does
* not have any token storage.
* slot 2 is our private key support. It requires a login before use. It
* can store Private Keys and Certs as token objects. Currently only private
* keys and their associated Certificates are saved on the token.
*
* In this implementation, session objects are only visible to the session
* that created or generated them.
*/
#include "sqlite3.h"
#include "mcom_db.h"
#include "errno.h"
#ifndef DARWIN
#include "malloc.h"
#endif
#include "stdlib.h"
#include "string.h"
#include "sys/stat.h"
#include "fcntl.h"
#ifdef _WINDOWS
#include "direct.h"
#define usleep(x)
#else
#include "unistd.h"
#endif
/*
* the following data structures should be moved to a 'rdb.h'.
*/
#define STATIC_CMD_SIZE 2048
struct RDBStr {
DB db;
int (*xactstart)(DB *db);
int (*xactdone)(DB *db, PRBool abort);
int version;
int (*dbinitcomplete)(DB *db);
int flags;
int index;
unsigned char *dataPool;
int dataPoolSize;
unsigned char *keyPool;
int keyPoolSize;
sqlite3_stmt *delStmt;
sqlite3_stmt *getStmt;
sqlite3_stmt *seqStmt;
sqlite3_stmt *insertStmt;
sqlite3_stmt *replaceStmt;
sqlite3_stmt *beginStmt;
sqlite3_stmt *rollbackStmt;
sqlite3_stmt *commitStmt;
};
typedef struct RDBStr RDB;
#define DB_RDB ((DBTYPE) 0xff)
#define RDB_RDONLY 1
#define RDB_RDWR 2
#define RDB_CREATE 4
#define DBM_OK 0
#define DBM_ERROR -1
#define DBM_END 1
#define DEL_CMD "DELETE FROM nssTable WHERE key=$KEY;"
#define GET_CMD "SELECT ALL * FROM nssTable WHERE key=$KEY;"
#define SEQ_CMD "SELECT ALL * FROM nssTable LIMIT 1 OFFSET $OFFSET;"
#define INSERT_CMD "INSERT INTO nssTable VALUES ( $KEY, $DATA );"
#define REPLACE_CMD "REPLACE INTO nssTable VALUES ( $KEY, $DATA );"
#define BEGIN_CMD "BEGIN EXCLUSIVE TRANSACTION;"
#define ROLLBACK_CMD "ROLLBACK TRANSACTION;"
#define COMMIT_CMD "COMMIT TRANSACTION;"
#define INIT_CMD \
"CREATE TABLE nssTable (Key PRIMARY KEY UNIQUE ON CONFLICT ABORT, Data);"
#define IN_INIT_CMD "CREATE TABLE nssInit (dummy);"
#define DONE_INIT_CMD "DROP TABLE nssInit;"
#define CHECK_TABLE_CMD "SELECT ALL * FROM %s LIMIT 0;"
static int rdbupdateStmt(sqlite3 *db, sqlite3_stmt **stmt, const char *cmd)
{
sqlite3_finalize(*stmt);
return sqlite3_prepare(db, cmd, -1, stmt, NULL);
}
#define MAX_RETRIES 10
static int rdbdone(int err, int *count)
{
/* allow as many rows as the database wants to give */
if (err == SQLITE_ROW) {
*count = 0;
return 0;
}
if (err != SQLITE_BUSY) {
return 1;
}
/* err == SQLITE_BUSY, Dont' retry forever in this case */
if (++(*count) >= MAX_RETRIES) {
return 1;
}
return 0;
}
static int rdbmapSQLError(sqlite3 *db, int sqlerr)
{
if ((sqlerr == SQLITE_OK) ||
(sqlerr == SQLITE_DONE)) {
return DBM_OK;
} else {
return DBM_ERROR;
}
}
int rdbxactstart(DB *db)
{
sqlite3 *psqlDB = (sqlite3 *)db->internal;
RDB *rdb = (RDB *)db;
sqlite3_stmt *stmt;
int retry = 0;
int sqlerr;
if (psqlDB == NULL) {
return DBM_ERROR;
}
if (rdb->flags == RDB_RDONLY) {
errno = EPERM;
return DBM_ERROR;
}
sqlerr = rdbupdateStmt(psqlDB, &rdb->beginStmt, BEGIN_CMD);
if (sqlerr != SQLITE_OK) {
return DBM_ERROR;
}
stmt = rdb->beginStmt;
do {
sqlerr = sqlite3_step(stmt);
if (sqlerr == SQLITE_BUSY) {
usleep(5);
}
} while (!rdbdone(sqlerr,&retry));
sqlite3_reset(stmt);
return rdbmapSQLError(psqlDB, sqlerr);
}
int rdbxactdone(DB *db, PRBool abort)
{
sqlite3 *psqlDB = (sqlite3 *)db->internal;
RDB *rdb = (RDB *)db;
sqlite3_stmt *stmt;
int retry = 0;
int sqlerr;
if (psqlDB == NULL) {
return DBM_ERROR;
}
if (rdb->flags == RDB_RDONLY) {
errno = EPERM;
return DBM_ERROR;
}
sqlerr = rdbupdateStmt(psqlDB, &rdb->rollbackStmt, ROLLBACK_CMD);
if (sqlerr != SQLITE_OK) {
return DBM_ERROR;
}
sqlerr = rdbupdateStmt(psqlDB, &rdb->commitStmt, COMMIT_CMD);
if (sqlerr != SQLITE_OK) {
return DBM_ERROR;
}
stmt = abort ? rdb->rollbackStmt : rdb->commitStmt;
do {
sqlerr = sqlite3_step(stmt);
if (sqlerr == SQLITE_BUSY) {
usleep(5);
}
} while (!rdbdone(sqlerr,&retry));
sqlite3_reset(stmt);
return rdbmapSQLError(psqlDB, sqlerr);
}
int rdbclose(DB *db)
{
sqlite3 *psqlDB = (sqlite3 *)db->internal;
RDB *rdb = (RDB *)db;
int sqlerr = SQLITE_OK;
sqlite3_finalize(rdb->delStmt);
sqlite3_finalize(rdb->getStmt);
sqlite3_finalize(rdb->seqStmt);
sqlite3_finalize(rdb->insertStmt);
sqlite3_finalize(rdb->replaceStmt);
sqlite3_finalize(rdb->beginStmt);
sqlite3_finalize(rdb->rollbackStmt);
sqlite3_finalize(rdb->commitStmt);
sqlerr = sqlite3_close(psqlDB);
/* assert sqlerr == SQLITE_OK */
free(rdb);
return DBM_OK;
}
int rdbdel(const DB *db, const DBT *key, uint flags)
{
sqlite3 *psqlDB = (sqlite3 *)db->internal;
RDB *rdb = (RDB *)db;
sqlite3_stmt *stmt;
int retry = 0;
int sqlerr;
if (psqlDB == NULL) {
return DBM_ERROR;
}
if (rdb->flags == RDB_RDONLY) {
errno = EPERM;
return DBM_ERROR;
}
sqlerr = rdbupdateStmt(psqlDB, &rdb->delStmt, DEL_CMD);
if (sqlerr != SQLITE_OK) {
return DBM_ERROR;
}
stmt = rdb->delStmt;
sqlite3_bind_blob(stmt, 1, key->data, key->size, SQLITE_STATIC);
do {
sqlerr = sqlite3_step(stmt);
if (sqlerr == SQLITE_BUSY) {
usleep(5);
}
} while (!rdbdone(sqlerr,&retry));
sqlite3_reset(stmt);
sqlite3_bind_null(stmt,1);
return rdbmapSQLError(psqlDB, sqlerr);
}
void
setData(DBT *dbt,const char *blobData, int blobSize,
unsigned char **poolPtr, int *poolSizePtr)
{
int size = blobSize < 2048 ? blobSize : 2048;
if (size > *poolSizePtr) {
*poolPtr = realloc(*poolPtr,size);
*poolSizePtr = size;
}
memcpy(*poolPtr, blobData, blobSize);
dbt->data = *poolPtr;
dbt->size = blobSize;
}
int rdbget(const DB *db, const DBT *key, DBT *data, uint flags)
{
sqlite3 *psqlDB = (sqlite3 *)db->internal;
RDB *rdb = (RDB *)db;
sqlite3_stmt *stmt;
int retry = 0;
int found = 0;
int sqlerr;
int ret;
if (psqlDB == NULL) {
return DBM_ERROR;
}
sqlerr = rdbupdateStmt(psqlDB, &rdb->getStmt, GET_CMD);
if (sqlerr != SQLITE_OK) {
return DBM_ERROR;
}
stmt = rdb->getStmt;
sqlite3_bind_blob(stmt, 1, key->data, key->size, SQLITE_STATIC);
do {
sqlerr = sqlite3_step(stmt);
if (sqlerr == SQLITE_BUSY) {
usleep(5);
}
if (sqlerr == SQLITE_ROW) {
/* we only asked for 1, this will return the last one */
int blobSize = sqlite3_column_bytes(stmt, 1);
const char *blobData = sqlite3_column_blob(stmt, 1);
setData(data,blobData,blobSize, &rdb->dataPool, &rdb->dataPoolSize);
found = 1;
}
} while (!rdbdone(sqlerr,&retry));
sqlite3_reset(stmt);
sqlite3_bind_null(stmt,1);
ret = rdbmapSQLError(psqlDB, sqlerr);
if ((ret == 0) && (!found)) {
ret = DBM_END;
}
return ret;
}
int rdbput(const DB *db, const DBT *key, const DBT *data, uint flag)
{
sqlite3 *psqlDB = (sqlite3 *)db->internal;
RDB *rdb = (RDB *)db;
sqlite3_stmt *stmt;
int retry = 0;
int sqlerr;
if (psqlDB == NULL) {
return DBM_ERROR;
}
if (rdb->flags == RDB_RDONLY) {
errno = EPERM;
return DBM_ERROR;
}
sqlerr = rdbupdateStmt(psqlDB, &rdb->insertStmt, INSERT_CMD);
if (sqlerr != SQLITE_OK) {
return DBM_ERROR;
}
sqlerr = rdbupdateStmt(psqlDB, &rdb->replaceStmt, REPLACE_CMD);
if (sqlerr != SQLITE_OK) {
return DBM_ERROR;
}
stmt = (flag == R_NOOVERWRITE) ? rdb->insertStmt : rdb->replaceStmt;
sqlite3_bind_blob(stmt, 1, key->data, key->size, SQLITE_STATIC);
sqlite3_bind_blob(stmt, 2, data->data, data->size, SQLITE_STATIC);
do {
sqlerr = sqlite3_step(stmt);
if (sqlerr == SQLITE_BUSY) {
usleep(5);
}
} while (!rdbdone(sqlerr,&retry));
sqlite3_reset(stmt);
sqlite3_bind_null(stmt,1);
sqlite3_bind_null(stmt,0);
return rdbmapSQLError(psqlDB, sqlerr);
}
int rdbseq(const DB *db, DBT *key, DBT *data, uint flags)
{
sqlite3 *psqlDB = (sqlite3 *)db->internal;
RDB *rdb = (RDB *)db;
sqlite3_stmt *stmt;
int retry = 0;
int found = 0;
int sqlerr;
int ret;
if (psqlDB == NULL) {
return DBM_ERROR;
}
if (flags == R_FIRST) {
rdb->index = 0;
} else if (flags == R_NEXT) {
rdb->index++;
} else {
errno = EINVAL;
return DBM_ERROR;
}
sqlerr = rdbupdateStmt(psqlDB, &rdb->seqStmt, SEQ_CMD);
if (sqlerr != SQLITE_OK) {
return DBM_ERROR;
}
stmt = rdb->seqStmt;
sqlite3_bind_int(stmt, 1, rdb->index);
do {
sqlerr = sqlite3_step(stmt);
if (sqlerr == SQLITE_BUSY) {
usleep(5);
}
if (sqlerr == SQLITE_ROW) {
/* we only asked for 1, this will return the last one */
int blobSize = sqlite3_column_bytes(stmt, 0);
const char *blobData = sqlite3_column_blob(stmt, 0);
setData(key,blobData,blobSize, &rdb->keyPool, &rdb->keyPoolSize);
blobSize = sqlite3_column_bytes(stmt, 1);
blobData = sqlite3_column_blob(stmt, 1);
setData(data,blobData,blobSize, &rdb->dataPool, &rdb->dataPoolSize);
found = 1;
}
} while (!rdbdone(sqlerr,&retry));
sqlite3_reset(stmt);
sqlite3_bind_null(stmt,1);
ret = rdbmapSQLError(psqlDB, sqlerr);
if ((ret == 0) && (!found)) {
ret = DBM_END;
}
return ret;
}
int rdbsync(const DB *db, uint flags)
{
return DBM_OK;
}
int rdbfd(const DB *db)
{
errno = EINVAL;
return DBM_ERROR;
}
int rdbinitcomplete(DB *db)
{
sqlite3 *psqlDB = (sqlite3 *)db->internal;
int sqlerr;
sqlerr = sqlite3_exec(psqlDB, DONE_INIT_CMD, NULL, 0, NULL);
/* deal with the error! */
return DBM_OK;
}
static int grdbstatus = 0;
int rdbstatus(void)
{
return grdbstatus;
}
static int tableExists(sqlite3 *sqlDB, const char *tableName)
{
int sqlerr;
char * cmd = sqlite3_mprintf(CHECK_TABLE_CMD, tableName);
if (cmd == NULL) {
return 0;
}
sqlerr =
sqlite3_exec(sqlDB, cmd, NULL, 0, 0);
sqlite3_free(cmd);
return (sqlerr == SQLITE_OK) ? 1 : 0;
}
static int rdbIsDirectory(const char *dir)
{
struct stat sbuf;
int rc;
rc = stat(dir,&sbuf);
if (rc == 0) {
return ((sbuf.st_mode & S_IFDIR) == S_IFDIR);
}
return 0;
}
static int rdbRmFile(const char *fileName)
{
int rc = unlink(fileName);
if ((rc < 0) && (errno == EPERM)) {
chmod(fileName,0644);
rc = unlink(fileName);
}
return rc;
}
#define MAX_RECURSE_LEVEL 15
#define DIR_MODE 0755
#ifdef _WINDOWS
#define MKDIR(x,y) mkdir(x)
#else
#define MKDIR(x,y) mkdir(x,y)
#endif
/*
* Create a directory. Create any missing or broken
* components we need along the way. If we already have a
* directory, return success.
*/
int rdbMakedir(const char *directory, int level, int mode)
{
int rc;
char *buf, *cp;
#ifdef _WINDOWS
char *cp1;
#endif
/* prevent arbitrary stack overflow */
if (level > MAX_RECURSE_LEVEL) {
errno = ENAMETOOLONG;
return -1;
}
umask(0);
/* just try it first */
rc = MKDIR(directory, mode);
if (rc != 0) {
if (errno == EEXIST) {
if (rdbIsDirectory(directory)) {
/* we have a directory, use it */
return 0;
} else { /* must be a file */
/* remove the file and try again */
rc = rdbRmFile(directory);
if (rc == 0) {
rc = MKDIR(directory, mode);
}
return rc;
}
}
/* if we fail because on of the subdirectory entries was a
* file, or one of the subdirectory entries didn't exist,
* move back one component and try the whole thing again
*/
if ((errno != ENOENT) && (errno != ENOTDIR)) {
return rc;
}
buf = (char *)malloc(strlen(directory)+1);
strcpy(buf,directory);
cp = strrchr(buf,'/');
#ifdef _WINDOWS
cp1 = strrchr(buf,'\\');
if (cp1 > cp) {
cp = cp1;
}
#endif
if (cp) {
*cp = 0;
rc = rdbMakedir(buf,level+1, mode);
if (rc == 0) {
rc = MKDIR(directory, mode);
}
}
free(buf);
}
return rc;
}
static char *rdbBuildFileName(const char *appName, const char *prefix,
const char *type, int flags)
{
const char *home = getenv("HOME");
char *dir, *dbname;
char *prefixDir = NULL;
const char *prefixName = NULL;
/*
* build up the name of our database file.
* if create is set, make sure the directory path exists.
*/
if (prefix) {
/*
* prefix may have directory elements in it. If it does, we need
* to break out the directory versus the actual prefix portions
* so we can make sure the directory is created before we try to
* create the db file.
*/
const char *end = strrchr(prefix,'/');
#ifdef WINDOWS
/* windows has two possible directory field separators. Make sure
* we pick the one that is furthest down the string. (this code
* will also pick the non-null value. */
const char *end2 = strrchr(prefix,'\\');
/* find the last directory path element */
if (end2 > end) {
end = end2;
}
#endif
/* if the directory path exists, split the components */
if (end) {
prefixDir = strdup(prefix);
if (prefixDir == NULL) return NULL;
prefixDir[prefix-end] = 0;
prefixName = end+1;
} else {
prefixName = prefix;
}
}
/* build the directory portion */
if (prefixDir) {
dir = sqlite3_mprintf("%s/.nssdb/%s/%s",home,appName,prefixDir);
free(prefixDir);
} else {
dir = sqlite3_mprintf("%s/.nssdb/%s",home,appName);
}
if (dir == NULL) return NULL;
/* if we are creating, make sure the directory is created as well */
if (flags == RDB_CREATE) {
rdbMakedir(dir,0, DIR_MODE);
}
/* build the full dbname */
dbname = sqlite3_mprintf("%s/%s%sS.sqldb",dir,prefixName? prefixName:"",type);
sqlite3_free(dir);
return dbname;
}
/* rdbopen */
DB * rdbopen(const char *appName, const char *prefix, const char *type,
int flags)
{
char *name = rdbBuildFileName(appName, prefix, type, flags);
sqlite3 *psqlDB = NULL;
RDB *rdb = NULL;
int sqlerr = SQLITE_OK;
int inTransaction = 0;
int inInit = 0;
if (name == NULL) {
errno = EINVAL;
return NULL;
}
sqlerr = sqlite3_open(name,&psqlDB );
sqlite3_free(name);
if (sqlerr != SQLITE_OK) {
goto cleanup;
}
sqlerr = sqlite3_busy_timeout(psqlDB, 1000);
if (sqlerr != SQLITE_OK) {
goto cleanup;
}
sqlerr = sqlite3_exec(psqlDB, BEGIN_CMD, NULL, 0, NULL);
if (sqlerr != SQLITE_OK) {
goto cleanup;
}
inTransaction = 1;
if (!tableExists(psqlDB,"nssTable")) {
if (flags != RDB_CREATE) {
goto cleanup;
}
sqlerr = sqlite3_exec(psqlDB, INIT_CMD, NULL, 0, NULL);
if (sqlerr != SQLITE_OK) {
goto cleanup;
}
/* hack. don't create the init on secmod db files */
if (strcmp(type,"secmod") != 0) {
sqlerr = sqlite3_exec(psqlDB, IN_INIT_CMD, NULL, 0, NULL);
if (sqlerr != SQLITE_OK) {
goto cleanup;
}
}
} else {
/* if the nssInit table exists, then someone else is initing the
* nss database. We don't want to complete the open until the init
* is completed. */
if (tableExists(psqlDB,"nssInit")) {
inInit = 1;
}
}
rdb = (RDB *) malloc(sizeof(RDB));
rdb->db.internal = psqlDB;
rdb->db.type = DB_RDB;
rdb->db.close = rdbclose;
rdb->db.del = rdbdel;
rdb->db.get = rdbget;
rdb->db.put = rdbput;
rdb->db.seq = rdbseq;
rdb->db.sync = rdbsync;
rdb->db.fd = rdbfd;
rdb->version = 1;
rdb->index = 0;
rdb->flags = flags;
rdb->xactstart = rdbxactstart;
rdb->xactdone = rdbxactdone;
rdb->dbinitcomplete = rdbinitcomplete;
rdb->dataPool = NULL;
rdb->dataPoolSize = 0;
rdb->keyPool = NULL;
rdb->keyPoolSize = 0;
sqlerr = sqlite3_prepare(psqlDB, DEL_CMD, sizeof(DEL_CMD),
&rdb->delStmt, NULL);
if (sqlerr != SQLITE_OK) {
goto cleanup;
}
sqlerr = sqlite3_prepare(psqlDB, GET_CMD, sizeof(GET_CMD),
&rdb->getStmt, NULL);
if (sqlerr != SQLITE_OK) {
goto cleanup;
}
sqlerr = sqlite3_prepare(psqlDB, SEQ_CMD, sizeof(SEQ_CMD),
&rdb->seqStmt, NULL);
if (sqlerr != SQLITE_OK) {
goto cleanup;
}
sqlerr = sqlite3_prepare(psqlDB, INSERT_CMD, sizeof(INSERT_CMD),
&rdb->insertStmt, NULL);
if (sqlerr != SQLITE_OK) {
goto cleanup;
}
sqlerr = sqlite3_prepare(psqlDB, REPLACE_CMD, sizeof(REPLACE_CMD),
&rdb->replaceStmt, NULL);
if (sqlerr != SQLITE_OK) {
goto cleanup;
}
sqlerr = sqlite3_prepare(psqlDB, BEGIN_CMD, sizeof(BEGIN_CMD),
&rdb->beginStmt, NULL);
if (sqlerr != SQLITE_OK) {
goto cleanup;
}
sqlerr = sqlite3_prepare(psqlDB, ROLLBACK_CMD, sizeof(ROLLBACK_CMD),
&rdb->rollbackStmt, NULL);
if (sqlerr != SQLITE_OK) {
goto cleanup;
}
sqlerr = sqlite3_prepare(psqlDB, COMMIT_CMD, sizeof(COMMIT_CMD),
&rdb->commitStmt, NULL);
if (sqlerr != SQLITE_OK) {
goto cleanup;
}
sqlerr = sqlite3_exec(psqlDB, COMMIT_CMD, NULL, 0, NULL);
if (sqlerr != SQLITE_OK) {
goto cleanup;
}
inTransaction = 0;
if (inInit) {
while (tableExists(psqlDB,"nssInit")) {
usleep(5);
}
}
return &rdb->db;
cleanup:
/* lots of stuff to do */
if (inTransaction) {
sqlerr = sqlite3_exec(psqlDB, ROLLBACK_CMD, NULL, 0, NULL);
if (sqlerr != SQLITE_OK) {
goto cleanup;
}
}
if (rdb) {
if (rdb->delStmt) {
sqlite3_finalize(rdb->delStmt);
}
if (rdb->getStmt) {
sqlite3_finalize(rdb->getStmt);
}
if (rdb->seqStmt) {
sqlite3_finalize(rdb->seqStmt);
}
if (rdb->insertStmt) {
sqlite3_finalize(rdb->insertStmt);
}
if (rdb->replaceStmt) {
sqlite3_finalize(rdb->replaceStmt);
}
if (rdb->beginStmt) {
sqlite3_finalize(rdb->beginStmt);
}
if (rdb->rollbackStmt) {
sqlite3_finalize(rdb->rollbackStmt);
}
if (rdb->commitStmt) {
sqlite3_finalize(rdb->commitStmt);
}
free(rdb);
}
if (psqlDB) {
sqlite3_close(psqlDB);
}
return NULL;
};

View File

@@ -1,59 +0,0 @@
;+#
;+# ***** BEGIN LICENSE BLOCK *****
;+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
;+#
;+# The contents of this file are subject to the Mozilla Public License Version
;+# 1.1 (the "License"); you may not use this file except in compliance with
;+# the License. You may obtain a copy of the License at
;+# http://www.mozilla.org/MPL/
;+#
;+# Software distributed under the License is distributed on an "AS IS" basis,
;+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
;+# for the specific language governing rights and limitations under the
;+# License.
;+#
;+# The Original Code is Red Hat, Inc.
;+#
;+# The Initial Developer of the Original Code is
;+# Red Hat, Inc.
;+# Portions created by the Initial Developer are Copyright (C) 2005
;+# the Initial Developer. All Rights Reserved.
;+#
;+# Contributor(s):
;+#
;+# Alternatively, the contents of this file may be used under the terms of
;+# either the GNU General Public License Version 2 or later (the "GPL"), or
;+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
;+# in which case the provisions of the GPL or the LGPL are applicable instead
;+# of those above. If you wish to allow use of your version of this file only
;+# under the terms of either the GPL or the LGPL, and not to allow others to
;+# use your version of this file under the terms of the MPL, indicate your
;+# decision by deleting the provisions above and replace them with the notice
;+# and other provisions required by the GPL or the LGPL. If you do not delete
;+# the provisions above, a recipient may use your version of this file under
;+# the terms of any one of the MPL, the GPL or the LGPL.
;+#
;+# ***** END LICENSE BLOCK *****
;+#
;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
;+# 1. For all unix platforms, the string ";-" means "remove this line"
;+# 2. For all unix platforms, the string " DATA " will be removed from any
;+# line on which it occurs.
;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
;+# On AIX, lines containing ";+" will be removed.
;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
;+# 5. For all unix platforms, after the above processing has taken place,
;+# all characters after the first ";" on the line will be removed.
;+# And for AIX, the first ";" will also be removed.
;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
;+# directives are hidden behind ";", ";+", and ";-"
;+
;+RDB_1.0 { # RDB 1.0
;+ global:
LIBRARY rdb ;-
EXPORTS ;-
rdbopen;
rdbstatus;
;+ local:
;+*;
;+};

View File

@@ -1,102 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert Relyea (rrelyea@redhat.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nss.h"
#include <winver.h>
#define MY_LIBNAME "rdb"
#define MY_FILEDESCRIPTION "NSS Multiaccess Database Library"
#define STRINGIZE(x) #x
#define STRINGIZE2(x) STRINGIZE(x)
#define NSS_VMAJOR_STR STRINGIZE2(NSS_VMAJOR)
#ifdef _DEBUG
#define MY_DEBUG_STR " (debug)"
#define MY_FILEFLAGS_1 VS_FF_DEBUG
#else
#define MY_DEBUG_STR ""
#define MY_FILEFLAGS_1 0x0L
#endif
#if NSS_BETA
#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
#else
#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
#endif
#ifdef WINNT
#define MY_FILEOS VOS_NT_WINDOWS32
#else
#define MY_FILEOS VOS__WINDOWS32
#endif
#define MY_INTERNAL_NAME MY_LIBNAME NSS_VMAJOR_STR
/////////////////////////////////////////////////////////////////////////////
//
// Version-information resource
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION NSS_VMAJOR,NSS_VMINOR,NSS_VPATCH,0
PRODUCTVERSION NSS_VMAJOR,NSS_VMINOR,NSS_VPATCH,0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS MY_FILEFLAGS_2
FILEOS MY_FILEOS
FILETYPE VFT_DLL
FILESUBTYPE 0x0L // not used
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904B0" // Lang=US English, CharSet=Unicode
BEGIN
VALUE "CompanyName", "Mozilla\0"
VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
VALUE "FileVersion", NSS_VERSION "\0"
VALUE "InternalName", MY_INTERNAL_NAME "\0"
VALUE "LegalCopyright", "Copyright \251 2005 Red Hat, Inc.\0"
VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
VALUE "ProductName", "Network Security Services\0"
VALUE "ProductVersion", NSS_VERSION "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View File

@@ -1,95 +0,0 @@
#! gmake
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape security libraries.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1994-2000
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
include config.mk
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
export:: private_export
# On AIX 4.3, IBM xlC_r compiler (version 3.6.6) cannot compile
# pkcs11c.c in 64-bit mode for unknown reasons. A workaround is
# to compile it with optimizations turned on. (Bugzilla bug #63815)
ifeq ($(OS_TARGET)$(OS_RELEASE),AIX4.3)
ifeq ($(USE_64),1)
ifndef BUILD_OPT
$(OBJDIR)/pkcs11.o: pkcs11.c
@$(MAKE_OBJDIR)
$(CC) -o $@ -c -O2 $(CFLAGS) $<
$(OBJDIR)/pkcs11c.o: pkcs11c.c
@$(MAKE_OBJDIR)
$(CC) -o $@ -c -O2 $(CFLAGS) $<
endif
endif
endif

View File

@@ -1,166 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "sechash.h"
#include "secport.h"
#include "alghmac.h"
#include "secerr.h"
#define HMAC_PAD_SIZE 64
struct HMACContextStr {
void *hash;
const SECHashObject *hashobj;
unsigned char ipad[HMAC_PAD_SIZE];
unsigned char opad[HMAC_PAD_SIZE];
};
void
HMAC_Destroy(HMACContext *cx)
{
if (cx == NULL)
return;
if (cx->hash != NULL)
cx->hashobj->destroy(cx->hash, PR_TRUE);
PORT_ZFree(cx, sizeof(HMACContext));
}
HMACContext *
HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret,
unsigned int secret_len, PRBool isFIPS)
{
HMACContext *cx;
unsigned int i;
unsigned char hashed_secret[HASH_LENGTH_MAX];
/* required by FIPS 198 Section 3 */
if (isFIPS && secret_len < hash_obj->length/2) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
cx = (HMACContext*)PORT_ZAlloc(sizeof(HMACContext));
if (cx == NULL)
return NULL;
cx->hashobj = hash_obj;
cx->hash = cx->hashobj->create();
if (cx->hash == NULL)
goto loser;
if (secret_len > HMAC_PAD_SIZE) {
cx->hashobj->begin( cx->hash);
cx->hashobj->update(cx->hash, secret, secret_len);
PORT_Assert(cx->hashobj->length <= sizeof hashed_secret);
cx->hashobj->end( cx->hash, hashed_secret, &secret_len,
sizeof hashed_secret);
if (secret_len != cx->hashobj->length)
goto loser;
secret = (const unsigned char *)&hashed_secret[0];
}
PORT_Memset(cx->ipad, 0x36, sizeof cx->ipad);
PORT_Memset(cx->opad, 0x5c, sizeof cx->opad);
/* fold secret into padding */
for (i = 0; i < secret_len; i++) {
cx->ipad[i] ^= secret[i];
cx->opad[i] ^= secret[i];
}
PORT_Memset(hashed_secret, 0, sizeof hashed_secret);
return cx;
loser:
PORT_Memset(hashed_secret, 0, sizeof hashed_secret);
HMAC_Destroy(cx);
return NULL;
}
void
HMAC_Begin(HMACContext *cx)
{
/* start inner hash */
cx->hashobj->begin(cx->hash);
cx->hashobj->update(cx->hash, cx->ipad, sizeof(cx->ipad));
}
void
HMAC_Update(HMACContext *cx, const unsigned char *data, unsigned int data_len)
{
cx->hashobj->update(cx->hash, data, data_len);
}
SECStatus
HMAC_Finish(HMACContext *cx, unsigned char *result, unsigned int *result_len,
unsigned int max_result_len)
{
if (max_result_len < cx->hashobj->length) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
cx->hashobj->end(cx->hash, result, result_len, max_result_len);
if (*result_len != cx->hashobj->length)
return SECFailure;
cx->hashobj->begin(cx->hash);
cx->hashobj->update(cx->hash, cx->opad, sizeof(cx->opad));
cx->hashobj->update(cx->hash, result, *result_len);
cx->hashobj->end(cx->hash, result, result_len, max_result_len);
return SECSuccess;
}
HMACContext *
HMAC_Clone(HMACContext *cx)
{
HMACContext *newcx;
newcx = (HMACContext*)PORT_ZAlloc(sizeof(HMACContext));
if (newcx == NULL)
goto loser;
newcx->hashobj = cx->hashobj;
newcx->hash = cx->hashobj->clone(cx->hash);
if (newcx->hash == NULL)
goto loser;
PORT_Memcpy(newcx->ipad, cx->ipad, sizeof(cx->ipad));
PORT_Memcpy(newcx->opad, cx->opad, sizeof(cx->opad));
return newcx;
loser:
HMAC_Destroy(newcx);
return NULL;
}

View File

@@ -1,91 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _ALGHMAC_H_
#define _ALGHMAC_H_
typedef struct HMACContextStr HMACContext;
SEC_BEGIN_PROTOS
/* destroy HMAC context */
extern void
HMAC_Destroy(HMACContext *cx);
/* create HMAC context
* hashObj hash object from SECRawHashObjects[]
* secret the secret with which the HMAC is performed.
* secret_len the length of the secret.
* isFIPS true if conforming to FIPS 198.
*
* NULL is returned if an error occurs.
*/
extern HMACContext *
HMAC_Create(const SECHashObject *hashObj, const unsigned char *secret,
unsigned int secret_len, PRBool isFIPS);
/* reset HMAC for a fresh round */
extern void
HMAC_Begin(HMACContext *cx);
/* update HMAC
* cx HMAC Context
* data the data to perform HMAC on
* data_len the length of the data to process
*/
extern void
HMAC_Update(HMACContext *cx, const unsigned char *data, unsigned int data_len);
/* Finish HMAC -- place the results within result
* cx HMAC context
* result buffer for resulting hmac'd data
* result_len where the resultant hmac length is stored
* max_result_len maximum possible length that can be stored in result
*/
extern SECStatus
HMAC_Finish(HMACContext *cx, unsigned char *result, unsigned int *result_len,
unsigned int max_result_len);
/* clone a copy of the HMAC state. this is usefult when you would
* need to keep a running hmac but also need to extract portions
* partway through the process.
*/
extern HMACContext *
HMAC_Clone(HMACContext *cx);
SEC_END_PROTOS
#endif

View File

@@ -1,85 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* cdbhdl.h - certificate database handle
* private to the certdb module
*
* $Id: cdbhdl.h,v 1.9 2004-04-25 15:03:16 gerv%gerv.net Exp $
*/
#ifndef _CDBHDL_H_
#define _CDBHDL_H_
#include "nspr.h"
#include "mcom_db.h"
#include "pcertt.h"
/*
* Handle structure for open certificate databases
*/
struct NSSLOWCERTCertDBHandleStr {
DB *permCertDB;
PZMonitor *dbMon;
PRBool dbVerify;
};
#ifdef DBM_USING_NSPR
#define NO_RDONLY PR_RDONLY
#define NO_RDWR PR_RDWR
#define NO_CREATE (PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE)
#else
#define NO_RDONLY O_RDONLY
#define NO_RDWR O_RDWR
#define NO_CREATE (O_RDWR | O_CREAT | O_TRUNC)
#endif
typedef DB * (*rdbfunc)(const char *appName, const char *prefix,
const char *type, int flags);
typedef int (*rdbstatusfunc)(void);
#define RDB_FAIL 1
#define RDB_RETRY 2
DB * rdbopen(const char *appName, const char *prefix,
const char *type, int flags, int *status);
DB *dbsopen (const char *dbname , int flags, int mode, DBTYPE type,
const void * appData);
SECStatus db_Copy(DB *dest,DB *src);
int db_BeginTransaction(DB *db);
int db_FinishTransaction(DB *db, PRBool abort);
int db_InitComplete(DB *db);
#endif

View File

@@ -1,98 +0,0 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape security libraries.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1994-2000
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX)
CRYPTODIR=../freebl
ifdef MOZILLA_SECURITY_BUILD
CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)crypto.$(LIB_SUFFIX)
CRYPTODIR=../crypto
endif
EXTRA_LIBS += \
$(CRYPTOLIB) \
$(DIST)/lib/$(LIB_PREFIX)secutil.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)dbm.$(LIB_SUFFIX) \
$(NULL)
# can't do this in manifest.mn because OS_TARGET isn't defined there.
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
# don't want the 32 in the shared library name
SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
IMPORT_LIBRARY = $(OBJDIR)/$(IMPORT_LIB_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION)$(IMPORT_LIB_SUFFIX)
RES = $(OBJDIR)/$(LIBRARY_NAME).res
RESNAME = $(LIBRARY_NAME).rc
ifdef NS_USE_GCC
EXTRA_SHARED_LIBS += \
-L$(DIST)/lib \
-lplc4 \
-lplds4 \
-lnspr4 \
$(NULL)
else # ! NS_USE_GCC
EXTRA_SHARED_LIBS += \
$(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4.lib \
$(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4.lib \
$(DIST)/lib/$(NSPR31_LIB_PREFIX)nspr4.lib \
$(NULL)
endif # NS_USE_GCC
else
# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
EXTRA_SHARED_LIBS += \
-L$(DIST)/lib/ \
-lplc4 \
-lplds4 \
-lnspr4 \
$(NULL)
endif
ifeq ($(OS_TARGET),SunOS)
# The -R '$ORIGIN' linker option instructs this library to search for its
# dependencies in the same directory where it resides.
MKSHLIB += -R '$$ORIGIN'
endif
ifeq ($(OS_TARGET),WINCE)
DEFINES += -DDBM_USING_NSPR
endif

View File

@@ -1,420 +0,0 @@
/*
* NSS utility functions
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: dbinit.c,v 1.25.8.1 2005-06-20 23:17:12 relyea%netscape.com Exp $ */
#include <ctype.h>
#include "seccomon.h"
#include "prinit.h"
#include "prprf.h"
#include "prmem.h"
#include "pcertt.h"
#include "lowkeyi.h"
#include "pcert.h"
#include "cdbhdl.h"
#include "pkcs11i.h"
#define ALWAYS_MULTIACCESS "CommonClient"
static char *
sftk_certdb_name_cb(void *arg, int dbVersion)
{
const char *configdir = (const char *)arg;
const char *dbver;
char *smpname = NULL;
char *dbname = NULL;
switch (dbVersion) {
case 8:
dbver = "8";
break;
case 7:
dbver = "7";
break;
case 6:
dbver = "6";
break;
case 5:
dbver = "5";
break;
case 4:
default:
dbver = "";
break;
}
/* make sure we return something allocated with PORT_ so we have properly
* matched frees at the end */
smpname = PR_smprintf(CERT_DB_FMT, configdir, dbver);
if (smpname) {
dbname = PORT_Strdup(smpname);
PR_smprintf_free(smpname);
}
return dbname;
}
static char *
sftk_keydb_name_cb(void *arg, int dbVersion)
{
const char *configdir = (const char *)arg;
const char *dbver;
char *smpname = NULL;
char *dbname = NULL;
switch (dbVersion) {
case 4:
dbver = "4";
break;
case 3:
dbver = "3";
break;
case 1:
dbver = "1";
break;
case 2:
default:
dbver = "";
break;
}
smpname = PR_smprintf(KEY_DB_FMT, configdir, dbver);
if (smpname) {
dbname = PORT_Strdup(smpname);
PR_smprintf_free(smpname);
}
return dbname;
}
const char *
sftk_EvaluateConfigDir(const char *configdir,char **appName)
{
#ifdef ALWAYS_MULTIACCESS
*appName = PORT_Strdup(ALWAYS_MULTIACCESS);
#else
if (PORT_Strncmp(configdir, MULTIACCESS, sizeof(MULTIACCESS)-1) == 0) {
char *cdir;
*appName = PORT_Strdup(configdir+sizeof(MULTIACCESS)-1);
if (*appName == NULL) {
return configdir;
}
cdir = *appName;
while (*cdir && *cdir != ':') {
cdir++;
}
if (*cdir == ':') {
*cdir = 0;
cdir++;
}
configdir = cdir;
}
#endif
return configdir;
}
static CK_RV
sftk_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly,
NSSLOWCERTCertDBHandle **certdbPtr)
{
NSSLOWCERTCertDBHandle *certdb = NULL;
CK_RV crv = CKR_NETSCAPE_CERTDB_FAILED;
SECStatus rv;
char * name = NULL;
char * appName = NULL;
if (prefix == NULL) {
prefix = "";
}
configdir = sftk_EvaluateConfigDir(configdir, &appName);
name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);
if (name == NULL) goto loser;
certdb = (NSSLOWCERTCertDBHandle*)PORT_ZAlloc(sizeof(NSSLOWCERTCertDBHandle));
if (certdb == NULL)
goto loser;
/* fix when we get the DB in */
rv = nsslowcert_OpenCertDB(certdb, readOnly, appName, prefix,
sftk_certdb_name_cb, (void *)name, PR_FALSE);
if (rv == SECSuccess) {
crv = CKR_OK;
*certdbPtr = certdb;
certdb = NULL;
}
loser:
if (certdb) PR_Free(certdb);
if (name) PR_smprintf_free(name);
if (appName) PORT_Free(appName);
return crv;
}
static CK_RV
sftk_OpenKeyDB(const char * configdir, const char *prefix, PRBool readOnly,
NSSLOWKEYDBHandle **keydbPtr)
{
NSSLOWKEYDBHandle *keydb;
char * name = NULL;
char * appName = NULL;
if (prefix == NULL) {
prefix = "";
}
configdir = sftk_EvaluateConfigDir(configdir, &appName);
name = PR_smprintf("%s" PATH_SEPARATOR "%s",configdir,prefix);
if (name == NULL)
return CKR_HOST_MEMORY;
keydb = nsslowkey_OpenKeyDB(readOnly, appName, prefix,
sftk_keydb_name_cb, (void *)name);
PR_smprintf_free(name);
if (appName) PORT_Free(appName);
if (keydb == NULL)
return CKR_NETSCAPE_KEYDB_FAILED;
*keydbPtr = keydb;
return CKR_OK;
}
/*
* OK there are now lots of options here, lets go through them all:
*
* configdir - base directory where all the cert, key, and module datbases live.
* certPrefix - prefix added to the beginning of the cert database example: "
* "https-server1-"
* keyPrefix - prefix added to the beginning of the key database example: "
* "https-server1-"
* secmodName - name of the security module database (usually "secmod.db").
* readOnly - Boolean: true if the databases are to be openned read only.
* nocertdb - Don't open the cert DB and key DB's, just initialize the
* Volatile certdb.
* nomoddb - Don't open the security module DB, just initialize the
* PKCS #11 module.
* forceOpen - Continue to force initializations even if the databases cannot
* be opened.
*/
CK_RV
sftk_DBInit(const char *configdir, const char *certPrefix,
const char *keyPrefix, PRBool readOnly,
PRBool noCertDB, PRBool noKeyDB, PRBool forceOpen,
NSSLOWCERTCertDBHandle **certdbPtr, NSSLOWKEYDBHandle **keydbPtr)
{
CK_RV crv = CKR_OK;
if (!noCertDB) {
crv = sftk_OpenCertDB(configdir, certPrefix, readOnly, certdbPtr);
if (crv != CKR_OK) {
if (!forceOpen) goto loser;
crv = CKR_OK;
}
}
if (!noKeyDB) {
crv = sftk_OpenKeyDB(configdir, keyPrefix, readOnly, keydbPtr);
if (crv != CKR_OK) {
if (!forceOpen) goto loser;
crv = CKR_OK;
}
}
loser:
return crv;
}
void
sftk_DBShutdown(NSSLOWCERTCertDBHandle *certHandle,
NSSLOWKEYDBHandle *keyHandle)
{
if (certHandle) {
nsslowcert_ClosePermCertDB(certHandle);
PORT_Free(certHandle);
}
if (keyHandle) {
nsslowkey_CloseKeyDB(keyHandle);
}
}
static int rdbmapflags(int flags);
static rdbfunc sftk_rdbfunc = NULL;
static rdbstatusfunc sftk_rdbstatusfunc = NULL;
/* NOTE: SHLIB_SUFFIX is defined on the command line */
#define RDBLIB SHLIB_PREFIX"rdb."SHLIB_SUFFIX
DB * rdbopen(const char *appName, const char *prefix,
const char *type, int flags, int *status)
{
PRLibrary *lib;
DB *db;
if (sftk_rdbfunc) {
db = (*sftk_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
if (!db && status && sftk_rdbstatusfunc) {
*status = (*sftk_rdbstatusfunc)();
}
return db;
}
/*
* try to open the library.
*/
lib = PR_LoadLibrary(RDBLIB);
if (!lib) {
return NULL;
}
/* get the entry points */
sftk_rdbstatusfunc = (rdbstatusfunc) PR_FindSymbol(lib,"rdbstatus");
sftk_rdbfunc = (rdbfunc) PR_FindSymbol(lib,"rdbopen");
if (sftk_rdbfunc) {
db = (*sftk_rdbfunc)(appName,prefix,type,rdbmapflags(flags));
if (!db && status && sftk_rdbstatusfunc) {
*status = (*sftk_rdbstatusfunc)();
}
return db;
}
/* couldn't find the entry point, unload the library and fail */
PR_UnloadLibrary(lib);
return NULL;
}
/*
* the following data structures are from rdb.h.
*/
struct RDBStr {
DB db;
int (*xactstart)(DB *db);
int (*xactdone)(DB *db, PRBool abort);
int version;
int (*dbinitcomplete)(DB *db);
};
#define DB_RDB ((DBTYPE) 0xff)
#define RDB_RDONLY 1
#define RDB_RDWR 2
#define RDB_CREATE 4
static int
rdbmapflags(int flags) {
switch (flags) {
case NO_RDONLY:
return RDB_RDONLY;
case NO_RDWR:
return RDB_RDWR;
case NO_CREATE:
return RDB_CREATE;
default:
break;
}
return 0;
}
PRBool
db_IsRDB(DB *db)
{
return (PRBool) db->type == DB_RDB;
}
int
db_BeginTransaction(DB *db)
{
struct RDBStr *rdb = (struct RDBStr *)db;
if (db->type != DB_RDB) {
return 0;
}
return rdb->xactstart(db);
}
int
db_FinishTransaction(DB *db, PRBool abort)
{
struct RDBStr *rdb = (struct RDBStr *)db;
if (db->type != DB_RDB) {
return 0;
}
return rdb->xactdone(db, abort);
}
int
db_InitComplete(DB *db)
{
struct RDBStr *rdb = (struct RDBStr *)db;
if (db->type != DB_RDB) {
return 0;
}
/* we should have addes a version number to the RDBS structure. Since we
* didn't, we detect that we have and 'extended' structure if the rdbstatus
* func exists */
if (!sftk_rdbstatusfunc) {
return 0;
}
return rdb->dbinitcomplete(db);
}
SECStatus
db_Copy(DB *dest,DB *src)
{
int ret;
DBT key,data;
ret = (*src->seq)(src, &key, &data, R_FIRST);
if (ret) {
return SECSuccess;
}
do {
(void)(*dest->put)(dest,&key,&data, R_NOOVERWRITE);
} while ( (*src->seq)(src, &key, &data, R_NEXT) == 0);
(void)(*dest->sync)(dest,0);
return SECSuccess;
}

View File

@@ -1,664 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* Berkeley DB 1.85 Shim code to handle blobs.
*
* $Id: dbmshim.c,v 1.11 2005-03-29 18:21:18 nelsonb%netscape.com Exp $
*/
#include "mcom_db.h"
#include "secitem.h"
#include "secder.h"
#include "prprf.h"
#include "cdbhdl.h"
/* Call to SFTK_FreeSlot below */
#include "pcertt.h"
#include "secasn1.h"
#include "secerr.h"
#include "nssb64.h"
#include "blapi.h"
#include "sechash.h"
#include "pkcs11i.h"
/*
* Blob block:
* Byte 0 CERTDB Version -+ -+
* Byte 1 certDBEntryTypeBlob | BLOB_HEAD_LEN |
* Byte 2 flags (always '0'); | |
* Byte 3 reserved (always '0'); -+ |
* Byte 4 LSB length | <--BLOB_LENGTH_START | BLOB_BUF_LEN
* Byte 5 . | |
* Byte 6 . | BLOB_LENGTH_LEN |
* Byte 7 MSB length | |
* Byte 8 blob_filename -+ -+ <-- BLOB_NAME_START |
* Byte 9 . | BLOB_NAME_LEN |
* . . | |
* Byte 37 . -+ -+
*/
#define DBS_BLOCK_SIZE (16*1024) /* 16 k */
#define DBS_MAX_ENTRY_SIZE (DBS_BLOCK_SIZE - (2048)) /* 14 k */
#define DBS_CACHE_SIZE DBS_BLOCK_SIZE*8
#define ROUNDDIV(x,y) (x+(y-1))/y
#define BLOB_HEAD_LEN 4
#define BLOB_LENGTH_START BLOB_HEAD_LEN
#define BLOB_LENGTH_LEN 4
#define BLOB_NAME_START BLOB_LENGTH_START+BLOB_LENGTH_LEN
#define BLOB_NAME_LEN 1+ROUNDDIV(SHA1_LENGTH,3)*4+1
#define BLOB_BUF_LEN BLOB_HEAD_LEN+BLOB_LENGTH_LEN+BLOB_NAME_LEN
/* a Shim data structure. This data structure has a db built into it. */
typedef struct DBSStr DBS;
struct DBSStr {
DB db;
char *blobdir;
int mode;
PRBool readOnly;
PRFileMap *dbs_mapfile;
unsigned char *dbs_addr;
PRUint32 dbs_len;
char staticBlobArea[BLOB_BUF_LEN];
};
/*
* return true if the Datablock contains a blobtype
*/
static PRBool
dbs_IsBlob(DBT *blobData)
{
unsigned char *addr = (unsigned char *)blobData->data;
if (blobData->size < BLOB_BUF_LEN) {
return PR_FALSE;
}
return addr && ((certDBEntryType) addr[1] == certDBEntryTypeBlob);
}
/*
* extract the filename in the blob of the real data set.
* This value is not malloced (does not need to be freed by the caller.
*/
static const char *
dbs_getBlobFileName(DBT *blobData)
{
char *addr = (char *)blobData->data;
return &addr[BLOB_NAME_START];
}
/*
* extract the size of the actual blob from the blob record
*/
static PRUint32
dbs_getBlobSize(DBT *blobData)
{
unsigned char *addr = (unsigned char *)blobData->data;
return (PRUint32)(addr[BLOB_LENGTH_START+3] << 24) |
(addr[BLOB_LENGTH_START+2] << 16) |
(addr[BLOB_LENGTH_START+1] << 8) |
addr[BLOB_LENGTH_START];
}
/* We are using base64 data for the filename, but base64 data can include a
* '/' which is interpreted as a path separator on many platforms. Replace it
* with an inocuous '-'. We don't need to convert back because we never actual
* decode the filename.
*/
static void
dbs_replaceSlash(char *cp, int len)
{
while (len--) {
if (*cp == '/') *cp = '-';
cp++;
}
}
/*
* create a blob record from a key, data and return it in blobData.
* NOTE: The data element is static data (keeping with the dbm model).
*/
static void
dbs_mkBlob(DBS *dbsp,const DBT *key, const DBT *data, DBT *blobData)
{
unsigned char sha1_data[SHA1_LENGTH];
char *b = dbsp->staticBlobArea;
PRUint32 length = data->size;
SECItem sha1Item;
b[0] = CERT_DB_FILE_VERSION; /* certdb version number */
b[1] = (char) certDBEntryTypeBlob; /* type */
b[2] = 0; /* flags */
b[3] = 0; /* reserved */
b[BLOB_LENGTH_START] = length & 0xff;
b[BLOB_LENGTH_START+1] = (length >> 8) & 0xff;
b[BLOB_LENGTH_START+2] = (length >> 16) & 0xff;
b[BLOB_LENGTH_START+3] = (length >> 24) & 0xff;
sha1Item.data = sha1_data;
sha1Item.len = SHA1_LENGTH;
SHA1_HashBuf(sha1_data,key->data,key->size);
b[BLOB_NAME_START]='b'; /* Make sure we start with a alpha */
NSSBase64_EncodeItem(NULL,&b[BLOB_NAME_START+1],BLOB_NAME_LEN-1,&sha1Item);
b[BLOB_BUF_LEN-1] = 0;
dbs_replaceSlash(&b[BLOB_NAME_START+1],BLOB_NAME_LEN-1);
blobData->data = b;
blobData->size = BLOB_BUF_LEN;
return;
}
/*
* construct a path to the actual blob. The string returned must be
* freed by the caller with PR_smprintf_free.
*
* Note: this file does lots of consistancy checks on the DBT. The
* routines that call this depend on these checks, so they don't worry
* about them (success of this routine implies a good blobdata record).
*/
static char *
dbs_getBlobFilePath(char *blobdir,DBT *blobData)
{
const char *name;
if (blobdir == NULL) {
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
return NULL;
}
if (!dbs_IsBlob(blobData)) {
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
return NULL;
}
name = dbs_getBlobFileName(blobData);
if (!name || *name == 0) {
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
return NULL;
}
return PR_smprintf("%s" PATH_SEPARATOR "%s", blobdir, name);
}
/*
* Delete a blob file pointed to by the blob record.
*/
static void
dbs_removeBlob(DBS *dbsp, DBT *blobData)
{
char *file;
file = dbs_getBlobFilePath(dbsp->blobdir, blobData);
if (!file) {
return;
}
PR_Delete(file);
PR_smprintf_free(file);
}
/*
* Directory modes are slightly different, the 'x' bit needs to be on to
* access them. Copy all the read bits to 'x' bits
*/
static int
dbs_DirMode(int mode)
{
int x_bits = (mode >> 2) & 0111;
return mode | x_bits;
}
/*
* write a data blob to it's file. blobdData is the blob record that will be
* stored in the database. data is the actual data to go out on disk.
*/
static int
dbs_writeBlob(DBS *dbsp, int mode, DBT *blobData, const DBT *data)
{
char *file = NULL;
PRFileDesc *filed;
PRStatus status;
int len;
int error = 0;
file = dbs_getBlobFilePath(dbsp->blobdir, blobData);
if (!file) {
goto loser;
}
if (PR_Access(dbsp->blobdir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
status = PR_MkDir(dbsp->blobdir,dbs_DirMode(mode));
if (status != PR_SUCCESS) {
goto loser;
}
}
filed = PR_OpenFile(file,PR_CREATE_FILE|PR_TRUNCATE|PR_WRONLY, mode);
if (filed == NULL) {
error = PR_GetError();
goto loser;
}
len = PR_Write(filed,data->data,data->size);
error = PR_GetError();
PR_Close(filed);
if (len < (int)data->size) {
goto loser;
}
PR_smprintf_free(file);
return 0;
loser:
if (file) {
PR_Delete(file);
PR_smprintf_free(file);
}
/* don't let close or delete reset the error */
PR_SetError(error,0);
return -1;
}
/*
* we need to keep a address map in memory between calls to DBM.
* remember what we have mapped can close it when we get another dbm
* call.
*
* NOTE: Not all platforms support mapped files. This code is designed to
* detect this at runtime. If map files aren't supported the OS will indicate
* this by failing the PR_Memmap call. In this case we emulate mapped files
* by just reading in the file into regular memory. We signal this state by
* making dbs_mapfile NULL and dbs_addr non-NULL.
*/
static void
dbs_freemap(DBS *dbsp)
{
if (dbsp->dbs_mapfile) {
PR_MemUnmap(dbsp->dbs_addr,dbsp->dbs_len);
PR_CloseFileMap(dbsp->dbs_mapfile);
dbsp->dbs_mapfile = NULL;
dbsp->dbs_addr = NULL;
dbsp->dbs_len = 0;
} else if (dbsp->dbs_addr) {
PORT_Free(dbsp->dbs_addr);
dbsp->dbs_addr = NULL;
dbsp->dbs_len = 0;
}
return;
}
static void
dbs_setmap(DBS *dbsp, PRFileMap *mapfile, unsigned char *addr, PRUint32 len)
{
dbsp->dbs_mapfile = mapfile;
dbsp->dbs_addr = addr;
dbsp->dbs_len = len;
}
/*
* platforms that cannot map the file need to read it into a temp buffer.
*/
static unsigned char *
dbs_EmulateMap(PRFileDesc *filed, int len)
{
unsigned char *addr;
PRInt32 dataRead;
addr = PORT_Alloc(len);
if (addr == NULL) {
return NULL;
}
dataRead = PR_Read(filed,addr,len);
if (dataRead != len) {
PORT_Free(addr);
if (dataRead > 0) {
/* PR_Read didn't set an error, we need to */
PR_SetError(SEC_ERROR_BAD_DATABASE,0);
}
return NULL;
}
return addr;
}
/*
* pull a database record off the disk
* data points to the blob record on input and the real record (if we could
* read it) on output. if there is an error data is not modified.
*/
static int
dbs_readBlob(DBS *dbsp, DBT *data)
{
char *file = NULL;
PRFileDesc *filed = NULL;
PRFileMap *mapfile = NULL;
unsigned char *addr = NULL;
int error;
int len = -1;
file = dbs_getBlobFilePath(dbsp->blobdir, data);
if (!file) {
goto loser;
}
filed = PR_OpenFile(file,PR_RDONLY,0);
PR_smprintf_free(file); file = NULL;
if (filed == NULL) {
goto loser;
}
len = dbs_getBlobSize(data);
mapfile = PR_CreateFileMap(filed, len, PR_PROT_READONLY);
if (mapfile == NULL) {
/* USE PR_GetError instead of PORT_GetError here
* because we are getting the error from PR_xxx
* function */
if (PR_GetError() != PR_NOT_IMPLEMENTED_ERROR) {
goto loser;
}
addr = dbs_EmulateMap(filed, len);
} else {
addr = PR_MemMap(mapfile, 0, len);
}
if (addr == NULL) {
goto loser;
}
PR_Close(filed);
dbs_setmap(dbsp,mapfile,addr,len);
data->data = addr;
data->size = len;
return 0;
loser:
/* preserve the error code */
error = PR_GetError();
if (addr) {
if (mapfile) {
PORT_Assert(len != -1);
PR_MemUnmap(addr,len);
} else {
PORT_Free(addr);
}
}
if (mapfile) {
PR_CloseFileMap(mapfile);
}
if (filed) {
PR_Close(filed);
}
PR_SetError(error,0);
return -1;
}
/*
* actual DBM shims
*/
static int
dbs_get(const DB *dbs, const DBT *key, DBT *data, unsigned int flags)
{
int ret;
DBS *dbsp = (DBS *)dbs;
DB *db = (DB *)dbs->internal;
dbs_freemap(dbsp);
ret = (* db->get)(db, key, data, flags);
if ((ret == 0) && dbs_IsBlob(data)) {
ret = dbs_readBlob(dbsp,data);
}
return(ret);
}
static int
dbs_put(const DB *dbs, DBT *key, const DBT *data, unsigned int flags)
{
DBT blob;
int ret = 0;
DBS *dbsp = (DBS *)dbs;
DB *db = (DB *)dbs->internal;
dbs_freemap(dbsp);
/* If the db is readonly, just pass the data down to rdb and let it fail */
if (!dbsp->readOnly) {
DBT oldData;
int ret1;
/* make sure the current record is deleted if it's a blob */
ret1 = (*db->get)(db,key,&oldData,0);
if ((ret1 == 0) && flags == R_NOOVERWRITE) {
/* let DBM return the error to maintain consistancy */
return (* db->put)(db, key, data, flags);
}
if ((ret1 == 0) && dbs_IsBlob(&oldData)) {
dbs_removeBlob(dbsp, &oldData);
}
if (data->size > DBS_MAX_ENTRY_SIZE) {
dbs_mkBlob(dbsp,key,data,&blob);
ret = dbs_writeBlob(dbsp, dbsp->mode, &blob, data);
data = &blob;
}
}
if (ret == 0) {
ret = (* db->put)(db, key, data, flags);
}
return(ret);
}
static int
dbs_sync(const DB *dbs, unsigned int flags)
{
DB *db = (DB *)dbs->internal;
DBS *dbsp = (DBS *)dbs;
dbs_freemap(dbsp);
return (* db->sync)(db, flags);
}
static int
dbs_del(const DB *dbs, const DBT *key, unsigned int flags)
{
int ret;
DBS *dbsp = (DBS *)dbs;
DB *db = (DB *)dbs->internal;
dbs_freemap(dbsp);
if (!dbsp->readOnly) {
DBT oldData;
ret = (*db->get)(db,key,&oldData,0);
if ((ret == 0) && dbs_IsBlob(&oldData)) {
dbs_removeBlob(dbsp,&oldData);
}
}
return (* db->del)(db, key, flags);
}
static int
dbs_seq(const DB *dbs, DBT *key, DBT *data, unsigned int flags)
{
int ret;
DBS *dbsp = (DBS *)dbs;
DB *db = (DB *)dbs->internal;
dbs_freemap(dbsp);
ret = (* db->seq)(db, key, data, flags);
if ((ret == 0) && dbs_IsBlob(data)) {
/* don't return a blob read as an error so traversals keep going */
(void) dbs_readBlob(dbsp,data);
}
return(ret);
}
static int
dbs_close(DB *dbs)
{
DBS *dbsp = (DBS *)dbs;
DB *db = (DB *)dbs->internal;
int ret;
dbs_freemap(dbsp);
ret = (* db->close)(db);
PORT_Free(dbsp->blobdir);
PORT_Free(dbsp);
return ret;
}
static int
dbs_fd(const DB *dbs)
{
DB *db = (DB *)dbs->internal;
return (* db->fd)(db);
}
/*
* the naming convention we use is
* change the .xxx into .dir. (for nss it's always .db);
* if no .extension exists or is equal to .dir, add a .dir
* the returned data must be freed.
*/
#define DIRSUFFIX ".dir"
static char *
dbs_mkBlobDirName(const char *dbname)
{
int dbname_len = PORT_Strlen(dbname);
int dbname_end = dbname_len;
const char *cp;
char *blobDir = NULL;
/* scan back from the end looking for either a directory separator, a '.',
* or the end of the string. NOTE: Windows should check for both separators
* here. For now this is safe because we know NSS always uses a '.'
*/
for (cp = &dbname[dbname_len];
(cp > dbname) && (*cp != '.') && (*cp != *PATH_SEPARATOR) ;
cp--)
/* Empty */ ;
if (*cp == '.') {
dbname_end = cp - dbname;
if (PORT_Strcmp(cp,DIRSUFFIX) == 0) {
dbname_end = dbname_len;
}
}
blobDir = PORT_ZAlloc(dbname_end+sizeof(DIRSUFFIX));
if (blobDir == NULL) {
return NULL;
}
PORT_Memcpy(blobDir,dbname,dbname_end);
PORT_Memcpy(&blobDir[dbname_end],DIRSUFFIX,sizeof(DIRSUFFIX));
return blobDir;
}
#define DBM_DEFAULT 0
static const HASHINFO dbs_hashInfo = {
DBS_BLOCK_SIZE, /* bucket size, must be greater than = to
* or maximum entry size (+ header)
* we allow before blobing */
DBM_DEFAULT, /* Fill Factor */
DBM_DEFAULT, /* number of elements */
DBS_CACHE_SIZE, /* cache size */
DBM_DEFAULT, /* hash function */
DBM_DEFAULT, /* byte order */
};
/*
* the open function. NOTE: this is the only exposed function in this file.
* everything else is called through the function table pointer.
*/
DB *
dbsopen(const char *dbname, int flags, int mode, DBTYPE type,
const void *userData)
{
DB *db = NULL,*dbs = NULL;
DBS *dbsp = NULL;
/* NOTE: we are overriding userData with dbs_hashInfo. since all known
* callers pass 0, this is ok, otherwise we should merge the two */
dbsp = (DBS *)PORT_ZAlloc(sizeof(DBS));
if (!dbsp) {
return NULL;
}
dbs = &dbsp->db;
dbsp->blobdir=dbs_mkBlobDirName(dbname);
if (dbsp->blobdir == NULL) {
goto loser;
}
dbsp->mode = mode;
dbsp->readOnly = (PRBool)(flags == NO_RDONLY);
dbsp->dbs_mapfile = NULL;
dbsp->dbs_addr = NULL;
dbsp->dbs_len = 0;
/* the real dbm call */
db = dbopen(dbname, flags, mode, type, &dbs_hashInfo);
if (db == NULL) {
goto loser;
}
dbs->internal = (void *) db;
dbs->type = type;
dbs->close = dbs_close;
dbs->get = dbs_get;
dbs->del = dbs_del;
dbs->put = dbs_put;
dbs->seq = dbs_seq;
dbs->sync = dbs_sync;
dbs->fd = dbs_fd;
return dbs;
loser:
if (db) {
(*db->close)(db);
}
if (dbsp && dbsp->blobdir) {
PORT_Free(dbsp->blobdir);
}
if (dbsp) {
PORT_Free(dbsp);
}
return NULL;
}

View File

@@ -1,687 +0,0 @@
/*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Elliptic Curve Cryptography library.
*
* The Initial Developer of the Original Code is
* Sun Microsystems, Inc.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dr Vipul Gupta <vipul.gupta@sun.com> and
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifdef NSS_ENABLE_ECC
#include "blapi.h"
#include "secoid.h"
#include "secitem.h"
#include "secerr.h"
#include "ec.h"
#include "ecl-curve.h"
#define CHECK_OK(func) if (func == NULL) goto cleanup
#define CHECK_SEC_OK(func) if (SECSuccess != (rv = func)) goto cleanup
/* Initializes a SECItem from a hexadecimal string */
static SECItem *
hexString2SECItem(PRArenaPool *arena, SECItem *item, const char *str)
{
int i = 0;
int byteval = 0;
int tmp = PORT_Strlen(str);
if ((tmp % 2) != 0) return NULL;
item->data = (unsigned char *) PORT_ArenaAlloc(arena, tmp/2);
if (item->data == NULL) return NULL;
item->len = tmp/2;
while (str[i]) {
if ((str[i] >= '0') && (str[i] <= '9'))
tmp = str[i] - '0';
else if ((str[i] >= 'a') && (str[i] <= 'f'))
tmp = str[i] - 'a' + 10;
else if ((str[i] >= 'A') && (str[i] <= 'F'))
tmp = str[i] - 'A' + 10;
else
return NULL;
byteval = byteval * 16 + tmp;
if ((i % 2) != 0) {
item->data[i/2] = byteval;
byteval = 0;
}
i++;
}
return item;
}
/* Copy all of the fields from srcParams into dstParams
*/
SECStatus
EC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
const ECParams *srcParams)
{
SECStatus rv = SECFailure;
dstParams->arena = arena;
dstParams->type = srcParams->type;
dstParams->fieldID.size = srcParams->fieldID.size;
dstParams->fieldID.type = srcParams->fieldID.type;
if (srcParams->fieldID.type == ec_field_GFp) {
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.prime,
&srcParams->fieldID.u.prime));
} else {
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.poly,
&srcParams->fieldID.u.poly));
}
dstParams->fieldID.k1 = srcParams->fieldID.k1;
dstParams->fieldID.k2 = srcParams->fieldID.k2;
dstParams->fieldID.k3 = srcParams->fieldID.k3;
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.a,
&srcParams->curve.a));
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.b,
&srcParams->curve.b));
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.seed,
&srcParams->curve.seed));
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->base,
&srcParams->base));
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->order,
&srcParams->order));
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->DEREncoding,
&srcParams->DEREncoding));
dstParams->name = srcParams->name;
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curveOID,
&srcParams->curveOID));
dstParams->cofactor = srcParams->cofactor;
return SECSuccess;
cleanup:
return SECFailure;
}
SECStatus
EC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
ECParams *params)
{
SECOidTag tag;
SECItem oid = { siBuffer, NULL, 0};
const ECCurveParams *curveParams;
char genenc[2 + 2 * 2 * MAX_ECKEY_LEN];
#if EC_DEBUG
int i;
printf("Encoded params in EC_DecodeParams: ");
for (i = 0; i < encodedParams->len; i++) {
printf("%02x:", encodedParams->data[i]);
}
printf("\n");
#endif
if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) &&
(encodedParams->len != SECG_CURVE_OID_TOTAL_LEN)) {
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
return SECFailure;
};
oid.len = encodedParams->len - 2;
oid.data = encodedParams->data + 2;
if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) {
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
return SECFailure;
}
params->arena = arena;
params->cofactor = 0;
params->type = ec_params_named;
params->name = ECCurve_noName;
/* For named curves, fill out curveOID */
params->curveOID.len = oid.len;
params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(arena, oid.len);
if (params->curveOID.data == NULL) goto cleanup;
memcpy(params->curveOID.data, oid.data, oid.len);
#if EC_DEBUG
printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag));
#endif
switch (tag) {
#define GF2M_POPULATE \
if ((params->name < ECCurve_noName) || \
(params->name > ECCurve_pastLastCurve)) goto cleanup; \
CHECK_OK(curveParams); \
params->fieldID.size = curveParams->size; \
params->fieldID.type = ec_field_GF2m; \
CHECK_OK(hexString2SECItem(params->arena, &params->fieldID.u.poly, \
curveParams->irr)); \
CHECK_OK(hexString2SECItem(params->arena, &params->curve.a, \
curveParams->curvea)); \
CHECK_OK(hexString2SECItem(params->arena, &params->curve.b, \
curveParams->curveb)); \
genenc[0] = '0'; \
genenc[1] = '4'; \
genenc[2] = '\0'; \
CHECK_OK(strcat(genenc, curveParams->genx)); \
CHECK_OK(strcat(genenc, curveParams->geny)); \
CHECK_OK(hexString2SECItem(params->arena, &params->base, \
genenc)); \
CHECK_OK(hexString2SECItem(params->arena, &params->order, \
curveParams->order)); \
params->cofactor = curveParams->cofactor;
case SEC_OID_ANSIX962_EC_C2PNB163V1:
/* Populate params for c2pnb163v1 */
params->name = ECCurve_X9_62_CHAR2_PNB163V1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_ANSIX962_EC_C2PNB163V2:
/* Populate params for c2pnb163v2 */
params->name = ECCurve_X9_62_CHAR2_PNB163V2;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_ANSIX962_EC_C2PNB163V3:
/* Populate params for c2pnb163v3 */
params->name = ECCurve_X9_62_CHAR2_PNB163V3;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_ANSIX962_EC_C2PNB176V1:
/* Populate params for c2pnb176v1 */
params->name = ECCurve_X9_62_CHAR2_PNB176V1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_ANSIX962_EC_C2TNB191V1:
/* Populate params for c2tnb191v1 */
params->name = ECCurve_X9_62_CHAR2_TNB191V1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_ANSIX962_EC_C2TNB191V2:
/* Populate params for c2tnb191v2 */
params->name = ECCurve_X9_62_CHAR2_TNB191V2;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_ANSIX962_EC_C2TNB191V3:
/* Populate params for c2tnb191v3 */
params->name = ECCurve_X9_62_CHAR2_TNB191V3;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_ANSIX962_EC_C2PNB208W1:
/* Populate params for c2pnb208w1 */
params->name = ECCurve_X9_62_CHAR2_PNB208W1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_ANSIX962_EC_C2TNB239V1:
/* Populate params for c2tnb239v1 */
params->name = ECCurve_X9_62_CHAR2_TNB239V1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_ANSIX962_EC_C2TNB239V2:
/* Populate params for c2tnb239v2 */
params->name = ECCurve_X9_62_CHAR2_TNB239V2;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_ANSIX962_EC_C2TNB239V3:
/* Populate params for c2tnb239v3 */
params->name = ECCurve_X9_62_CHAR2_TNB239V3;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_ANSIX962_EC_C2PNB272W1:
/* Populate params for c2pnb272w1 */
params->name = ECCurve_X9_62_CHAR2_PNB272W1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_ANSIX962_EC_C2PNB304W1:
/* Populate params for c2pnb304w1 */
params->name = ECCurve_X9_62_CHAR2_PNB304W1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_ANSIX962_EC_C2TNB359V1:
/* Populate params for c2tnb359v1 */
params->name = ECCurve_X9_62_CHAR2_TNB359V1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_ANSIX962_EC_C2PNB368W1:
/* Populate params for c2pnb368w1 */
params->name = ECCurve_X9_62_CHAR2_PNB368W1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_ANSIX962_EC_C2TNB431R1:
/* Populate params for c2tnb431r1 */
params->name = ECCurve_X9_62_CHAR2_TNB431R1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT113R1:
/* Populate params for sect113r1 */
params->name = ECCurve_SECG_CHAR2_113R1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT113R2:
/* Populate params for sect113r2 */
params->name = ECCurve_SECG_CHAR2_113R2;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT131R1:
/* Populate params for sect131r1 */
params->name = ECCurve_SECG_CHAR2_131R1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT131R2:
/* Populate params for sect131r2 */
params->name = ECCurve_SECG_CHAR2_131R2;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT163K1:
/* Populate params for sect163k1
* (the NIST K-163 curve)
*/
params->name = ECCurve_SECG_CHAR2_163K1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT163R1:
/* Populate params for sect163r1 */
params->name = ECCurve_SECG_CHAR2_163R1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT163R2:
/* Populate params for sect163r2
* (the NIST B-163 curve)
*/
params->name = ECCurve_SECG_CHAR2_163R2;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT193R1:
/* Populate params for sect193r1 */
params->name = ECCurve_SECG_CHAR2_193R1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT193R2:
/* Populate params for sect193r2 */
params->name = ECCurve_SECG_CHAR2_193R2;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT233K1:
/* Populate params for sect233k1
* (the NIST K-233 curve)
*/
params->name = ECCurve_SECG_CHAR2_233K1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT233R1:
/* Populate params for sect233r1
* (the NIST B-233 curve)
*/
params->name = ECCurve_SECG_CHAR2_233R1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT239K1:
/* Populate params for sect239k1 */
params->name = ECCurve_SECG_CHAR2_239K1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT283K1:
/* Populate params for sect283k1
* (the NIST K-283 curve)
*/
params->name = ECCurve_SECG_CHAR2_283K1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT283R1:
/* Populate params for sect283r1
* (the NIST B-283 curve)
*/
params->name = ECCurve_SECG_CHAR2_283R1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT409K1:
/* Populate params for sect409k1
* (the NIST K-409 curve)
*/
params->name = ECCurve_SECG_CHAR2_409K1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT409R1:
/* Populate params for sect409r1
* (the NIST B-409 curve)
*/
params->name = ECCurve_SECG_CHAR2_409R1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT571K1:
/* Populate params for sect571k1
* (the NIST K-571 curve)
*/
params->name = ECCurve_SECG_CHAR2_571K1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
case SEC_OID_SECG_EC_SECT571R1:
/* Populate params for sect571r1
* (the NIST B-571 curve)
*/
params->name = ECCurve_SECG_CHAR2_571R1;
curveParams = ecCurve_map[params->name];
GF2M_POPULATE
break;
#define GFP_POPULATE \
if ((params->name < ECCurve_noName) || \
(params->name > ECCurve_pastLastCurve)) goto cleanup; \
CHECK_OK(curveParams); \
params->fieldID.size = curveParams->size; \
params->fieldID.type = ec_field_GFp; \
CHECK_OK(hexString2SECItem(params->arena, &params->fieldID.u.prime, \
curveParams->irr)); \
CHECK_OK(hexString2SECItem(params->arena, &params->curve.a, \
curveParams->curvea)); \
CHECK_OK(hexString2SECItem(params->arena, &params->curve.b, \
curveParams->curveb)); \
genenc[0] = '0'; \
genenc[1] = '4'; \
genenc[2] = '\0'; \
CHECK_OK(strcat(genenc, curveParams->genx)); \
CHECK_OK(strcat(genenc, curveParams->geny)); \
CHECK_OK(hexString2SECItem(params->arena, &params->base, \
genenc)); \
CHECK_OK(hexString2SECItem(params->arena, &params->order, \
curveParams->order)); \
params->cofactor = curveParams->cofactor;
case SEC_OID_ANSIX962_EC_PRIME192V1:
/* Populate params for prime192v1 aka secp192r1
* (the NIST P-192 curve)
*/
params->name = ECCurve_X9_62_PRIME_192V1;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_ANSIX962_EC_PRIME192V2:
/* Populate params for prime192v2 */
params->name = ECCurve_X9_62_PRIME_192V2;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_ANSIX962_EC_PRIME192V3:
/* Populate params for prime192v3 */
params->name = ECCurve_X9_62_PRIME_192V3;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_ANSIX962_EC_PRIME239V1:
/* Populate params for prime239v1 */
params->name = ECCurve_X9_62_PRIME_239V1;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_ANSIX962_EC_PRIME239V2:
/* Populate params for prime239v2 */
params->name = ECCurve_X9_62_PRIME_239V2;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_ANSIX962_EC_PRIME239V3:
/* Populate params for prime239v3 */
params->name = ECCurve_X9_62_PRIME_239V3;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_ANSIX962_EC_PRIME256V1:
/* Populate params for prime256v1 aka secp256r1
* (the NIST P-256 curve)
*/
params->name = ECCurve_X9_62_PRIME_256V1;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_SECG_EC_SECP112R1:
/* Populate params for secp112r1 */
params->name = ECCurve_SECG_PRIME_112R1;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_SECG_EC_SECP112R2:
/* Populate params for secp112r2 */
params->name = ECCurve_SECG_PRIME_112R2;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_SECG_EC_SECP128R1:
/* Populate params for secp128r1 */
params->name = ECCurve_SECG_PRIME_128R1;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_SECG_EC_SECP128R2:
/* Populate params for secp128r2 */
params->name = ECCurve_SECG_PRIME_128R2;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_SECG_EC_SECP160K1:
/* Populate params for secp160k1 */
params->name = ECCurve_SECG_PRIME_160K1;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_SECG_EC_SECP160R1:
/* Populate params for secp160r1 */
params->name = ECCurve_SECG_PRIME_160R1;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_SECG_EC_SECP160R2:
/* Populate params for secp160r1 */
params->name = ECCurve_SECG_PRIME_160R2;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_SECG_EC_SECP192K1:
/* Populate params for secp192k1 */
params->name = ECCurve_SECG_PRIME_192K1;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_SECG_EC_SECP224K1:
/* Populate params for secp224k1 */
params->name = ECCurve_SECG_PRIME_224K1;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_SECG_EC_SECP224R1:
/* Populate params for secp224r1
* (the NIST P-224 curve)
*/
params->name = ECCurve_SECG_PRIME_224R1;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_SECG_EC_SECP256K1:
/* Populate params for secp256k1 */
params->name = ECCurve_SECG_PRIME_256K1;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_SECG_EC_SECP384R1:
/* Populate params for secp384r1
* (the NIST P-384 curve)
*/
params->name = ECCurve_SECG_PRIME_384R1;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
case SEC_OID_SECG_EC_SECP521R1:
/* Populate params for secp521r1
* (the NIST P-521 curve)
*/
params->name = ECCurve_SECG_PRIME_521R1;
curveParams = ecCurve_map[params->name];
GFP_POPULATE
break;
default:
break;
};
cleanup:
if (!params->cofactor) {
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
#if EC_DEBUG
printf("Unrecognized curve, returning NULL params\n");
#endif
return SECFailure;
}
return SECSuccess;
}
SECStatus
EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams)
{
PRArenaPool *arena;
ECParams *params;
SECStatus rv = SECFailure;
/* Initialize an arena for the ECParams structure */
if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
return SECFailure;
params = (ECParams *)PORT_ArenaZAlloc(arena, sizeof(ECParams));
if (!params) {
PORT_FreeArena(arena, PR_TRUE);
return SECFailure;
}
/* Copy the encoded params */
SECITEM_AllocItem(arena, &(params->DEREncoding),
encodedParams->len);
memcpy(params->DEREncoding.data, encodedParams->data, encodedParams->len);
/* Fill out the rest of the ECParams structure based on
* the encoded params
*/
rv = EC_FillParams(arena, encodedParams, params);
if (rv == SECFailure) {
PORT_FreeArena(arena, PR_TRUE);
return SECFailure;
} else {
*ecparams = params;;
return SECSuccess;
}
}
#endif /* NSS_ENABLE_ECC */

File diff suppressed because it is too large Load Diff

View File

@@ -1,996 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* This file implements PKCS 11 on top of our existing security modules
*
* For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
* This implementation has two slots:
* slot 1 is our generic crypto support. It does not require login
* (unless you've enabled FIPS). It supports Public Key ops, and all they
* bulk ciphers and hashes. It can also support Private Key ops for imported
* Private keys. It does not have any token storage.
* slot 2 is our private key support. It requires a login before use. It
* can store Private Keys and Certs as token objects. Currently only private
* keys and their associated Certificates are saved on the token.
*
* In this implementation, session objects are only visible to the session
* that created or generated them.
*/
#include "seccomon.h"
#include "softoken.h"
#include "lowkeyi.h"
#include "pcert.h"
#include "pkcs11.h"
#include "pkcs11i.h"
/*
* ******************** Password Utilities *******************************
*/
static PRBool isLoggedIn = PR_FALSE;
static PRBool fatalError = PR_FALSE;
/* Fips required checks before any useful crypto graphic services */
static CK_RV sftk_fipsCheck(void) {
if (isLoggedIn != PR_TRUE)
return CKR_USER_NOT_LOGGED_IN;
if (fatalError)
return CKR_DEVICE_ERROR;
return CKR_OK;
}
#define SFTK_FIPSCHECK() \
CK_RV rv; \
if ((rv = sftk_fipsCheck()) != CKR_OK) return rv;
#define SFTK_FIPSFATALCHECK() \
if (fatalError) return CKR_DEVICE_ERROR;
/* grab an attribute out of a raw template */
void *
fc_getAttribute(CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount, CK_ATTRIBUTE_TYPE type)
{
int i;
for (i=0; i < (int) ulCount; i++) {
if (pTemplate[i].type == type) {
return pTemplate[i].pValue;
}
}
return NULL;
}
#define __PASTE(x,y) x##y
/* ------------- forward declare all the NSC_ functions ------------- */
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
#define CK_PKCS11_FUNCTION_INFO(name) CK_RV __PASTE(NS,name)
#define CK_NEED_ARG_LIST 1
#include "pkcs11f.h"
/* ------------- forward declare all the FIPS functions ------------- */
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
#define CK_PKCS11_FUNCTION_INFO(name) CK_RV __PASTE(F,name)
#define CK_NEED_ARG_LIST 1
#include "pkcs11f.h"
/* ------------- build the CK_CRYPTO_TABLE ------------------------- */
static CK_FUNCTION_LIST sftk_fipsTable = {
{ 1, 10 },
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
#define CK_PKCS11_FUNCTION_INFO(name) __PASTE(F,name),
#include "pkcs11f.h"
};
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
#undef __PASTE
static CK_RV
fips_login_if_key_object(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
{
CK_RV rv;
CK_OBJECT_CLASS objClass;
CK_ATTRIBUTE class;
class.type = CKA_CLASS;
class.pValue = &objClass;
class.ulValueLen = sizeof(objClass);
rv = NSC_GetAttributeValue(hSession, hObject, &class, 1);
if (rv == CKR_OK) {
if ((objClass == CKO_PRIVATE_KEY) || (objClass == CKO_SECRET_KEY)) {
rv = sftk_fipsCheck();
}
}
return rv;
}
/**********************************************************************
*
* Start of PKCS 11 functions
*
**********************************************************************/
/* return the function list */
CK_RV FC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) {
*pFunctionList = &sftk_fipsTable;
return CKR_OK;
}
/* sigh global so pkcs11 can read it */
PRBool nsf_init = PR_FALSE;
/* FC_Initialize initializes the PKCS #11 library. */
CK_RV FC_Initialize(CK_VOID_PTR pReserved) {
CK_RV crv;
if (nsf_init) {
return CKR_CRYPTOKI_ALREADY_INITIALIZED;
}
crv = nsc_CommonInitialize(pReserved, PR_TRUE);
/* not an 'else' rv can be set by either SFTK_LowInit or SFTK_SlotInit*/
if (crv != CKR_OK) {
fatalError = PR_TRUE;
return crv;
}
fatalError = PR_FALSE; /* any error has been reset */
crv = sftk_fipsPowerUpSelfTest();
if (crv != CKR_OK) {
nsc_CommonFinalize(NULL, PR_TRUE);
fatalError = PR_TRUE;
return crv;
}
nsf_init = PR_TRUE;
return CKR_OK;
}
/*FC_Finalize indicates that an application is done with the PKCS #11 library.*/
CK_RV FC_Finalize (CK_VOID_PTR pReserved) {
CK_RV crv;
if (!nsf_init) {
return CKR_OK;
}
crv = nsc_CommonFinalize (pReserved, PR_TRUE);
nsf_init = (PRBool) !(crv == CKR_OK);
return crv;
}
/* FC_GetInfo returns general information about PKCS #11. */
CK_RV FC_GetInfo(CK_INFO_PTR pInfo) {
return NSC_GetInfo(pInfo);
}
/* FC_GetSlotList obtains a list of slots in the system. */
CK_RV FC_GetSlotList(CK_BBOOL tokenPresent,
CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) {
return nsc_CommonGetSlotList(tokenPresent,pSlotList,pulCount,
NSC_FIPS_MODULE);
}
/* FC_GetSlotInfo obtains information about a particular slot in the system. */
CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
CK_RV crv;
crv = NSC_GetSlotInfo(slotID,pInfo);
if (crv != CKR_OK) {
return crv;
}
return CKR_OK;
}
/*FC_GetTokenInfo obtains information about a particular token in the system.*/
CK_RV FC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) {
CK_RV crv;
crv = NSC_GetTokenInfo(slotID,pInfo);
pInfo->flags |= CKF_RNG | CKF_LOGIN_REQUIRED;
return crv;
}
/*FC_GetMechanismList obtains a list of mechanism types supported by a token.*/
CK_RV FC_GetMechanismList(CK_SLOT_ID slotID,
CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pusCount) {
SFTK_FIPSFATALCHECK();
if (slotID == FIPS_SLOT_ID) slotID = NETSCAPE_SLOT_ID;
/* FIPS Slot supports all functions */
return NSC_GetMechanismList(slotID,pMechanismList,pusCount);
}
/* FC_GetMechanismInfo obtains information about a particular mechanism
* possibly supported by a token. */
CK_RV FC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
CK_MECHANISM_INFO_PTR pInfo) {
SFTK_FIPSFATALCHECK();
if (slotID == FIPS_SLOT_ID) slotID = NETSCAPE_SLOT_ID;
/* FIPS Slot supports all functions */
return NSC_GetMechanismInfo(slotID,type,pInfo);
}
/* FC_InitToken initializes a token. */
CK_RV FC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin,
CK_ULONG usPinLen,CK_CHAR_PTR pLabel) {
return CKR_HOST_MEMORY; /*is this the right function for not implemented*/
}
/* FC_InitPIN initializes the normal user's PIN. */
CK_RV FC_InitPIN(CK_SESSION_HANDLE hSession,
CK_CHAR_PTR pPin, CK_ULONG ulPinLen) {
return NSC_InitPIN(hSession,pPin,ulPinLen);
}
/* FC_SetPIN modifies the PIN of user that is currently logged in. */
/* NOTE: This is only valid for the PRIVATE_KEY_SLOT */
CK_RV FC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
CK_ULONG usOldLen, CK_CHAR_PTR pNewPin, CK_ULONG usNewLen) {
CK_RV rv;
if ((rv = sftk_fipsCheck()) != CKR_OK) return rv;
return NSC_SetPIN(hSession,pOldPin,usOldLen,pNewPin,usNewLen);
}
/* FC_OpenSession opens a session between an application and a token. */
CK_RV FC_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags,
CK_VOID_PTR pApplication,CK_NOTIFY Notify,CK_SESSION_HANDLE_PTR phSession) {
SFTK_FIPSFATALCHECK();
return NSC_OpenSession(slotID,flags,pApplication,Notify,phSession);
}
/* FC_CloseSession closes a session between an application and a token. */
CK_RV FC_CloseSession(CK_SESSION_HANDLE hSession) {
return NSC_CloseSession(hSession);
}
/* FC_CloseAllSessions closes all sessions with a token. */
CK_RV FC_CloseAllSessions (CK_SLOT_ID slotID) {
return NSC_CloseAllSessions (slotID);
}
/* FC_GetSessionInfo obtains information about the session. */
CK_RV FC_GetSessionInfo(CK_SESSION_HANDLE hSession,
CK_SESSION_INFO_PTR pInfo) {
CK_RV rv;
SFTK_FIPSFATALCHECK();
rv = NSC_GetSessionInfo(hSession,pInfo);
if (rv == CKR_OK) {
if ((isLoggedIn) && (pInfo->state == CKS_RO_PUBLIC_SESSION)) {
pInfo->state = CKS_RO_USER_FUNCTIONS;
}
if ((isLoggedIn) && (pInfo->state == CKS_RW_PUBLIC_SESSION)) {
pInfo->state = CKS_RW_USER_FUNCTIONS;
}
}
return rv;
}
/* FC_Login logs a user into a token. */
CK_RV FC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
CK_CHAR_PTR pPin, CK_ULONG usPinLen) {
CK_RV rv;
SFTK_FIPSFATALCHECK();
rv = NSC_Login(hSession,userType,pPin,usPinLen);
if (rv == CKR_OK)
isLoggedIn = PR_TRUE;
else if (rv == CKR_USER_ALREADY_LOGGED_IN)
{
isLoggedIn = PR_TRUE;
/* Provide FIPS PUB 140-1 power-up self-tests on demand. */
rv = sftk_fipsPowerUpSelfTest();
if (rv == CKR_OK)
return CKR_USER_ALREADY_LOGGED_IN;
else
fatalError = PR_TRUE;
}
return rv;
}
/* FC_Logout logs a user out from a token. */
CK_RV FC_Logout(CK_SESSION_HANDLE hSession) {
SFTK_FIPSCHECK();
rv = NSC_Logout(hSession);
isLoggedIn = PR_FALSE;
return rv;
}
/* FC_CreateObject creates a new object. */
CK_RV FC_CreateObject(CK_SESSION_HANDLE hSession,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phObject) {
CK_OBJECT_CLASS * classptr;
SFTK_FIPSCHECK();
classptr = (CK_OBJECT_CLASS *)fc_getAttribute(pTemplate,ulCount,CKA_CLASS);
if (classptr == NULL) return CKR_TEMPLATE_INCOMPLETE;
/* FIPS can't create keys from raw key material */
if ((*classptr == CKO_SECRET_KEY) || (*classptr == CKO_PRIVATE_KEY)) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return NSC_CreateObject(hSession,pTemplate,ulCount,phObject);
}
/* FC_CopyObject copies an object, creating a new object for the copy. */
CK_RV FC_CopyObject(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount,
CK_OBJECT_HANDLE_PTR phNewObject) {
CK_RV rv;
SFTK_FIPSFATALCHECK();
rv = fips_login_if_key_object(hSession, hObject);
if (rv != CKR_OK) {
return rv;
}
return NSC_CopyObject(hSession,hObject,pTemplate,usCount,phNewObject);
}
/* FC_DestroyObject destroys an object. */
CK_RV FC_DestroyObject(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject) {
CK_RV rv;
SFTK_FIPSFATALCHECK();
rv = fips_login_if_key_object(hSession, hObject);
if (rv != CKR_OK) {
return rv;
}
return NSC_DestroyObject(hSession,hObject);
}
/* FC_GetObjectSize gets the size of an object in bytes. */
CK_RV FC_GetObjectSize(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pusSize) {
CK_RV rv;
SFTK_FIPSFATALCHECK();
rv = fips_login_if_key_object(hSession, hObject);
if (rv != CKR_OK) {
return rv;
}
return NSC_GetObjectSize(hSession, hObject, pusSize);
}
/* FC_GetAttributeValue obtains the value of one or more object attributes. */
CK_RV FC_GetAttributeValue(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG usCount) {
CK_RV rv;
SFTK_FIPSFATALCHECK();
rv = fips_login_if_key_object(hSession, hObject);
if (rv != CKR_OK) {
return rv;
}
return NSC_GetAttributeValue(hSession,hObject,pTemplate,usCount);
}
/* FC_SetAttributeValue modifies the value of one or more object attributes */
CK_RV FC_SetAttributeValue (CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG usCount) {
CK_RV rv;
SFTK_FIPSFATALCHECK();
rv = fips_login_if_key_object(hSession, hObject);
if (rv != CKR_OK) {
return rv;
}
return NSC_SetAttributeValue(hSession,hObject,pTemplate,usCount);
}
/* FC_FindObjectsInit initializes a search for token and session objects
* that match a template. */
CK_RV FC_FindObjectsInit(CK_SESSION_HANDLE hSession,
CK_ATTRIBUTE_PTR pTemplate,CK_ULONG usCount) {
/* let publically readable object be found */
int i;
CK_RV rv;
PRBool needLogin = PR_FALSE;
SFTK_FIPSFATALCHECK();
for (i=0; i < usCount; i++) {
CK_OBJECT_CLASS class;
if (pTemplate[i].type != CKA_CLASS) {
continue;
}
if (pTemplate[i].ulValueLen != sizeof(CK_OBJECT_CLASS)) {
continue;
}
if (pTemplate[i].pValue == NULL) {
continue;
}
class = *(CK_OBJECT_CLASS *)pTemplate[i].pValue;
if ((class == CKO_PRIVATE_KEY) || (class == CKO_SECRET_KEY)) {
needLogin = PR_TRUE;
break;
}
}
if (needLogin) {
if ((rv = sftk_fipsCheck()) != CKR_OK) return rv;
}
return NSC_FindObjectsInit(hSession,pTemplate,usCount);
}
/* FC_FindObjects continues a search for token and session objects
* that match a template, obtaining additional object handles. */
CK_RV FC_FindObjects(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE_PTR phObject,CK_ULONG usMaxObjectCount,
CK_ULONG_PTR pusObjectCount) {
/* let publically readable object be found */
SFTK_FIPSFATALCHECK();
return NSC_FindObjects(hSession,phObject,usMaxObjectCount,
pusObjectCount);
}
/*
************** Crypto Functions: Encrypt ************************
*/
/* FC_EncryptInit initializes an encryption operation. */
CK_RV FC_EncryptInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) {
SFTK_FIPSCHECK();
return NSC_EncryptInit(hSession,pMechanism,hKey);
}
/* FC_Encrypt encrypts single-part data. */
CK_RV FC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
CK_ULONG usDataLen, CK_BYTE_PTR pEncryptedData,
CK_ULONG_PTR pusEncryptedDataLen) {
SFTK_FIPSCHECK();
return NSC_Encrypt(hSession,pData,usDataLen,pEncryptedData,
pusEncryptedDataLen);
}
/* FC_EncryptUpdate continues a multiple-part encryption operation. */
CK_RV FC_EncryptUpdate(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pPart, CK_ULONG usPartLen, CK_BYTE_PTR pEncryptedPart,
CK_ULONG_PTR pusEncryptedPartLen) {
SFTK_FIPSCHECK();
return NSC_EncryptUpdate(hSession,pPart,usPartLen,pEncryptedPart,
pusEncryptedPartLen);
}
/* FC_EncryptFinal finishes a multiple-part encryption operation. */
CK_RV FC_EncryptFinal(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pusLastEncryptedPartLen) {
SFTK_FIPSCHECK();
return NSC_EncryptFinal(hSession,pLastEncryptedPart,
pusLastEncryptedPartLen);
}
/*
************** Crypto Functions: Decrypt ************************
*/
/* FC_DecryptInit initializes a decryption operation. */
CK_RV FC_DecryptInit( CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) {
SFTK_FIPSCHECK();
return NSC_DecryptInit(hSession,pMechanism,hKey);
}
/* FC_Decrypt decrypts encrypted data in a single part. */
CK_RV FC_Decrypt(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pEncryptedData,CK_ULONG usEncryptedDataLen,CK_BYTE_PTR pData,
CK_ULONG_PTR pusDataLen) {
SFTK_FIPSCHECK();
return NSC_Decrypt(hSession,pEncryptedData,usEncryptedDataLen,pData,
pusDataLen);
}
/* FC_DecryptUpdate continues a multiple-part decryption operation. */
CK_RV FC_DecryptUpdate(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pEncryptedPart, CK_ULONG usEncryptedPartLen,
CK_BYTE_PTR pPart, CK_ULONG_PTR pusPartLen) {
SFTK_FIPSCHECK();
return NSC_DecryptUpdate(hSession,pEncryptedPart,usEncryptedPartLen,
pPart,pusPartLen);
}
/* FC_DecryptFinal finishes a multiple-part decryption operation. */
CK_RV FC_DecryptFinal(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pLastPart, CK_ULONG_PTR pusLastPartLen) {
SFTK_FIPSCHECK();
return NSC_DecryptFinal(hSession,pLastPart,pusLastPartLen);
}
/*
************** Crypto Functions: Digest (HASH) ************************
*/
/* FC_DigestInit initializes a message-digesting operation. */
CK_RV FC_DigestInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism) {
SFTK_FIPSFATALCHECK();
return NSC_DigestInit(hSession, pMechanism);
}
/* FC_Digest digests data in a single part. */
CK_RV FC_Digest(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pData, CK_ULONG usDataLen, CK_BYTE_PTR pDigest,
CK_ULONG_PTR pusDigestLen) {
SFTK_FIPSFATALCHECK();
return NSC_Digest(hSession,pData,usDataLen,pDigest,pusDigestLen);
}
/* FC_DigestUpdate continues a multiple-part message-digesting operation. */
CK_RV FC_DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,
CK_ULONG usPartLen) {
SFTK_FIPSFATALCHECK();
return NSC_DigestUpdate(hSession,pPart,usPartLen);
}
/* FC_DigestFinal finishes a multiple-part message-digesting operation. */
CK_RV FC_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,
CK_ULONG_PTR pusDigestLen) {
SFTK_FIPSFATALCHECK();
return NSC_DigestFinal(hSession,pDigest,pusDigestLen);
}
/*
************** Crypto Functions: Sign ************************
*/
/* FC_SignInit initializes a signature (private key encryption) operation,
* where the signature is (will be) an appendix to the data,
* and plaintext cannot be recovered from the signature */
CK_RV FC_SignInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) {
SFTK_FIPSCHECK();
return NSC_SignInit(hSession,pMechanism,hKey);
}
/* FC_Sign signs (encrypts with private key) data in a single part,
* where the signature is (will be) an appendix to the data,
* and plaintext cannot be recovered from the signature */
CK_RV FC_Sign(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pData,CK_ULONG usDataLen,CK_BYTE_PTR pSignature,
CK_ULONG_PTR pusSignatureLen) {
SFTK_FIPSCHECK();
return NSC_Sign(hSession,pData,usDataLen,pSignature,pusSignatureLen);
}
/* FC_SignUpdate continues a multiple-part signature operation,
* where the signature is (will be) an appendix to the data,
* and plaintext cannot be recovered from the signature */
CK_RV FC_SignUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,
CK_ULONG usPartLen) {
SFTK_FIPSCHECK();
return NSC_SignUpdate(hSession,pPart,usPartLen);
}
/* FC_SignFinal finishes a multiple-part signature operation,
* returning the signature. */
CK_RV FC_SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,
CK_ULONG_PTR pusSignatureLen) {
SFTK_FIPSCHECK();
return NSC_SignFinal(hSession,pSignature,pusSignatureLen);
}
/*
************** Crypto Functions: Sign Recover ************************
*/
/* FC_SignRecoverInit initializes a signature operation,
* where the (digest) data can be recovered from the signature.
* E.g. encryption with the user's private key */
CK_RV FC_SignRecoverInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) {
SFTK_FIPSCHECK();
return NSC_SignRecoverInit(hSession,pMechanism,hKey);
}
/* FC_SignRecover signs data in a single operation
* where the (digest) data can be recovered from the signature.
* E.g. encryption with the user's private key */
CK_RV FC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
CK_ULONG usDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pusSignatureLen) {
SFTK_FIPSCHECK();
return NSC_SignRecover(hSession,pData,usDataLen,pSignature,pusSignatureLen);
}
/*
************** Crypto Functions: verify ************************
*/
/* FC_VerifyInit initializes a verification operation,
* where the signature is an appendix to the data,
* and plaintext cannot be recovered from the signature (e.g. DSA) */
CK_RV FC_VerifyInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) {
SFTK_FIPSCHECK();
return NSC_VerifyInit(hSession,pMechanism,hKey);
}
/* FC_Verify verifies a signature in a single-part operation,
* where the signature is an appendix to the data,
* and plaintext cannot be recovered from the signature */
CK_RV FC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
CK_ULONG usDataLen, CK_BYTE_PTR pSignature, CK_ULONG usSignatureLen) {
/* make sure we're legal */
SFTK_FIPSCHECK();
return NSC_Verify(hSession,pData,usDataLen,pSignature,usSignatureLen);
}
/* FC_VerifyUpdate continues a multiple-part verification operation,
* where the signature is an appendix to the data,
* and plaintext cannot be recovered from the signature */
CK_RV FC_VerifyUpdate( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
CK_ULONG usPartLen) {
SFTK_FIPSCHECK();
return NSC_VerifyUpdate(hSession,pPart,usPartLen);
}
/* FC_VerifyFinal finishes a multiple-part verification operation,
* checking the signature. */
CK_RV FC_VerifyFinal(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pSignature,CK_ULONG usSignatureLen) {
SFTK_FIPSCHECK();
return NSC_VerifyFinal(hSession,pSignature,usSignatureLen);
}
/*
************** Crypto Functions: Verify Recover ************************
*/
/* FC_VerifyRecoverInit initializes a signature verification operation,
* where the data is recovered from the signature.
* E.g. Decryption with the user's public key */
CK_RV FC_VerifyRecoverInit(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) {
SFTK_FIPSCHECK();
return NSC_VerifyRecoverInit(hSession,pMechanism,hKey);
}
/* FC_VerifyRecover verifies a signature in a single-part operation,
* where the data is recovered from the signature.
* E.g. Decryption with the user's public key */
CK_RV FC_VerifyRecover(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pSignature,CK_ULONG usSignatureLen,
CK_BYTE_PTR pData,CK_ULONG_PTR pusDataLen) {
SFTK_FIPSCHECK();
return NSC_VerifyRecover(hSession,pSignature,usSignatureLen,pData,
pusDataLen);
}
/*
**************************** Key Functions: ************************
*/
/* FC_GenerateKey generates a secret key, creating a new key object. */
CK_RV FC_GenerateKey(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phKey) {
CK_BBOOL *boolptr;
SFTK_FIPSCHECK();
/* all secret keys must be sensitive, if the upper level code tries to say
* otherwise, reject it. */
boolptr = (CK_BBOOL *) fc_getAttribute(pTemplate, ulCount, CKA_SENSITIVE);
if (boolptr != NULL) {
if (!(*boolptr)) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
}
return NSC_GenerateKey(hSession,pMechanism,pTemplate,ulCount,phKey);
}
/* FC_GenerateKeyPair generates a public-key/private-key pair,
* creating new key objects. */
CK_RV FC_GenerateKeyPair (CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate,
CK_ULONG usPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
CK_ULONG usPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey,
CK_OBJECT_HANDLE_PTR phPrivateKey) {
CK_BBOOL *boolptr;
SFTK_FIPSCHECK();
/* all private keys must be sensitive, if the upper level code tries to say
* otherwise, reject it. */
boolptr = (CK_BBOOL *) fc_getAttribute(pPrivateKeyTemplate,
usPrivateKeyAttributeCount, CKA_SENSITIVE);
if (boolptr != NULL) {
if (!(*boolptr)) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
}
return NSC_GenerateKeyPair (hSession,pMechanism,pPublicKeyTemplate,
usPublicKeyAttributeCount,pPrivateKeyTemplate,
usPrivateKeyAttributeCount,phPublicKey,phPrivateKey);
}
/* FC_WrapKey wraps (i.e., encrypts) a key. */
CK_RV FC_WrapKey(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey,
CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey,
CK_ULONG_PTR pusWrappedKeyLen) {
SFTK_FIPSCHECK();
return NSC_WrapKey(hSession,pMechanism,hWrappingKey,hKey,pWrappedKey,
pusWrappedKeyLen);
}
/* FC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
CK_RV FC_UnwrapKey(CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey,
CK_BYTE_PTR pWrappedKey, CK_ULONG usWrappedKeyLen,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usAttributeCount,
CK_OBJECT_HANDLE_PTR phKey) {
CK_BBOOL *boolptr;
SFTK_FIPSCHECK();
/* all secret keys must be sensitive, if the upper level code tries to say
* otherwise, reject it. */
boolptr = (CK_BBOOL *) fc_getAttribute(pTemplate,
usAttributeCount, CKA_SENSITIVE);
if (boolptr != NULL) {
if (!(*boolptr)) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
}
return NSC_UnwrapKey(hSession,pMechanism,hUnwrappingKey,pWrappedKey,
usWrappedKeyLen,pTemplate,usAttributeCount,phKey);
}
/* FC_DeriveKey derives a key from a base key, creating a new key object. */
CK_RV FC_DeriveKey( CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usAttributeCount,
CK_OBJECT_HANDLE_PTR phKey) {
CK_BBOOL *boolptr;
SFTK_FIPSCHECK();
/* all secret keys must be sensitive, if the upper level code tries to say
* otherwise, reject it. */
boolptr = (CK_BBOOL *) fc_getAttribute(pTemplate,
usAttributeCount, CKA_SENSITIVE);
if (boolptr != NULL) {
if (!(*boolptr)) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
}
return NSC_DeriveKey(hSession,pMechanism,hBaseKey,pTemplate,
usAttributeCount, phKey);
}
/*
**************************** Radom Functions: ************************
*/
/* FC_SeedRandom mixes additional seed material into the token's random number
* generator. */
CK_RV FC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
CK_ULONG usSeedLen) {
CK_RV crv;
SFTK_FIPSFATALCHECK();
crv = NSC_SeedRandom(hSession,pSeed,usSeedLen);
if (crv != CKR_OK) {
fatalError = PR_TRUE;
}
return crv;
}
/* FC_GenerateRandom generates random data. */
CK_RV FC_GenerateRandom(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pRandomData, CK_ULONG usRandomLen) {
CK_RV crv;
SFTK_FIPSFATALCHECK();
crv = NSC_GenerateRandom(hSession,pRandomData,usRandomLen);
if (crv != CKR_OK) {
fatalError = PR_TRUE;
}
return crv;
}
/* FC_GetFunctionStatus obtains an updated status of a function running
* in parallel with an application. */
CK_RV FC_GetFunctionStatus(CK_SESSION_HANDLE hSession) {
SFTK_FIPSCHECK();
return NSC_GetFunctionStatus(hSession);
}
/* FC_CancelFunction cancels a function running in parallel */
CK_RV FC_CancelFunction(CK_SESSION_HANDLE hSession) {
SFTK_FIPSCHECK();
return NSC_CancelFunction(hSession);
}
/*
**************************** Version 1.1 Functions: ************************
*/
/* FC_GetOperationState saves the state of the cryptographic
*operation in a session. */
CK_RV FC_GetOperationState(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) {
SFTK_FIPSFATALCHECK();
return NSC_GetOperationState(hSession,pOperationState,pulOperationStateLen);
}
/* FC_SetOperationState restores the state of the cryptographic operation
* in a session. */
CK_RV FC_SetOperationState(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen,
CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) {
SFTK_FIPSFATALCHECK();
return NSC_SetOperationState(hSession,pOperationState,ulOperationStateLen,
hEncryptionKey,hAuthenticationKey);
}
/* FC_FindObjectsFinal finishes a search for token and session objects. */
CK_RV FC_FindObjectsFinal(CK_SESSION_HANDLE hSession) {
/* let publically readable object be found */
SFTK_FIPSFATALCHECK();
return NSC_FindObjectsFinal(hSession);
}
/* Dual-function cryptographic operations */
/* FC_DigestEncryptUpdate continues a multiple-part digesting and encryption
* operation. */
CK_RV FC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
CK_ULONG_PTR pulEncryptedPartLen) {
SFTK_FIPSCHECK();
return NSC_DigestEncryptUpdate(hSession,pPart,ulPartLen,pEncryptedPart,
pulEncryptedPartLen);
}
/* FC_DecryptDigestUpdate continues a multiple-part decryption and digesting
* operation. */
CK_RV FC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) {
SFTK_FIPSCHECK();
return NSC_DecryptDigestUpdate(hSession, pEncryptedPart,ulEncryptedPartLen,
pPart,pulPartLen);
}
/* FC_SignEncryptUpdate continues a multiple-part signing and encryption
* operation. */
CK_RV FC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
CK_ULONG_PTR pulEncryptedPartLen) {
SFTK_FIPSCHECK();
return NSC_SignEncryptUpdate(hSession,pPart,ulPartLen,pEncryptedPart,
pulEncryptedPartLen);
}
/* FC_DecryptVerifyUpdate continues a multiple-part decryption and verify
* operation. */
CK_RV FC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) {
SFTK_FIPSCHECK();
return NSC_DecryptVerifyUpdate(hSession,pEncryptedData,ulEncryptedDataLen,
pData,pulDataLen);
}
/* FC_DigestKey continues a multi-part message-digesting operation,
* by digesting the value of a secret key as part of the data already digested.
*/
CK_RV FC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) {
SFTK_FIPSCHECK();
return NSC_DigestKey(hSession,hKey);
}
CK_RV FC_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot,
CK_VOID_PTR pReserved)
{
return NSC_WaitForSlotEvent(flags, pSlot, pReserved);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,84 +0,0 @@
/*
* private.h - Private data structures for the software token library
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: keydbi.h,v 1.6 2004-04-27 23:04:38 gerv%gerv.net Exp $ */
#ifndef _KEYDBI_H_
#define _KEYDBI_H_
#include "nspr.h"
#include "seccomon.h"
#include "mcom_db.h"
/*
* Handle structure for open key databases
*/
struct NSSLOWKEYDBHandleStr {
DB *db;
DB *updatedb; /* used when updating an old version */
SECItem *global_salt; /* password hashing salt for this db */
int version; /* version of the database */
char *appname; /* multiaccess app name */
char *dbname; /* name of the openned DB */
PRBool readOnly; /* is the DB read only */
};
/*
** Typedef for callback for traversing key database.
** "key" is the key used to index the data in the database (nickname)
** "data" is the key data
** "pdata" is the user's data
*/
typedef SECStatus (* NSSLOWKEYTraverseKeysFunc)(DBT *key, DBT *data, void *pdata);
SEC_BEGIN_PROTOS
/*
** Traverse the entire key database, and pass the nicknames and keys to a
** user supplied function.
** "f" is the user function to call for each key
** "udata" is the user's data, which is passed through to "f"
*/
extern SECStatus nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle,
NSSLOWKEYTraverseKeysFunc f,
void *udata);
SEC_END_PROTOS
#endif /* _KEYDBI_H_ */

View File

@@ -1,625 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* Certificate handling code
*
* $Id: lowcert.c,v 1.18 2004-04-25 15:03:16 gerv%gerv.net Exp $
*/
#include "seccomon.h"
#include "secder.h"
#include "nssilock.h"
#include "prmon.h"
#include "prtime.h"
#include "lowkeyi.h"
#include "pcert.h"
#include "secasn1.h"
#include "secoid.h"
#ifdef NSS_ENABLE_ECC
extern SECStatus EC_FillParams(PRArenaPool *arena,
const SECItem *encodedParams,
ECParams *params);
#endif
static const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTSubjectPublicKeyInfo) },
{ SEC_ASN1_INLINE, offsetof(NSSLOWCERTSubjectPublicKeyInfo,algorithm),
SECOID_AlgorithmIDTemplate },
{ SEC_ASN1_BIT_STRING,
offsetof(NSSLOWCERTSubjectPublicKeyInfo,subjectPublicKey), },
{ 0, }
};
static const SEC_ASN1Template nsslowcert_RSAPublicKeyTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPublicKey) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.modulus), },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.publicExponent), },
{ 0, }
};
static const SEC_ASN1Template nsslowcert_DSAPublicKeyTemplate[] = {
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dsa.publicValue), },
{ 0, }
};
static const SEC_ASN1Template nsslowcert_DHPublicKeyTemplate[] = {
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dh.publicValue), },
{ 0, }
};
/*
* See bugzilla bug 125359
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
* all of the templates above that en/decode into integers must be converted
* from ASN.1's signed integer type. This is done by marking either the
* source or destination (encoding or decoding, respectively) type as
* siUnsignedInteger.
*/
static void
prepare_low_rsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
{
pubk->u.rsa.modulus.type = siUnsignedInteger;
pubk->u.rsa.publicExponent.type = siUnsignedInteger;
}
static void
prepare_low_dsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
{
pubk->u.dsa.publicValue.type = siUnsignedInteger;
pubk->u.dsa.params.prime.type = siUnsignedInteger;
pubk->u.dsa.params.subPrime.type = siUnsignedInteger;
pubk->u.dsa.params.base.type = siUnsignedInteger;
}
static void
prepare_low_dh_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
{
pubk->u.dh.prime.type = siUnsignedInteger;
pubk->u.dh.base.type = siUnsignedInteger;
pubk->u.dh.publicValue.type = siUnsignedInteger;
}
/*
* Allow use of default cert database, so that apps(such as mozilla) don't
* have to pass the handle all over the place.
*/
static NSSLOWCERTCertDBHandle *default_pcert_db_handle = 0;
void
nsslowcert_SetDefaultCertDB(NSSLOWCERTCertDBHandle *handle)
{
default_pcert_db_handle = handle;
return;
}
NSSLOWCERTCertDBHandle *
nsslowcert_GetDefaultCertDB(void)
{
return(default_pcert_db_handle);
}
/*
* simple cert decoder to avoid the cost of asn1 engine
*/
static unsigned char *
nsslowcert_dataStart(unsigned char *buf, unsigned int length,
unsigned int *data_length, PRBool includeTag,
unsigned char* rettag) {
unsigned char tag;
unsigned int used_length= 0;
tag = buf[used_length++];
if (rettag) {
*rettag = tag;
}
/* blow out when we come to the end */
if (tag == 0) {
return NULL;
}
*data_length = buf[used_length++];
if (*data_length&0x80) {
int len_count = *data_length & 0x7f;
*data_length = 0;
while (len_count-- > 0) {
*data_length = (*data_length << 8) | buf[used_length++];
}
}
if (*data_length > (length-used_length) ) {
*data_length = length-used_length;
return NULL;
}
if (includeTag) *data_length += used_length;
return (buf + (includeTag ? 0 : used_length));
}
static void SetTimeType(SECItem* item, unsigned char tagtype)
{
switch (tagtype) {
case SEC_ASN1_UTC_TIME:
item->type = siUTCTime;
break;
case SEC_ASN1_GENERALIZED_TIME:
item->type = siGeneralizedTime;
break;
default:
PORT_Assert(0);
break;
}
}
static int
nsslowcert_GetValidityFields(unsigned char *buf,int buf_length,
SECItem *notBefore, SECItem *notAfter)
{
unsigned char tagtype;
notBefore->data = nsslowcert_dataStart(buf,buf_length,
&notBefore->len,PR_FALSE, &tagtype);
if (notBefore->data == NULL) return SECFailure;
SetTimeType(notBefore, tagtype);
buf_length -= (notBefore->data-buf) + notBefore->len;
buf = notBefore->data + notBefore->len;
notAfter->data = nsslowcert_dataStart(buf,buf_length,
&notAfter->len,PR_FALSE, &tagtype);
if (notAfter->data == NULL) return SECFailure;
SetTimeType(notAfter, tagtype);
return SECSuccess;
}
static int
nsslowcert_GetCertFields(unsigned char *cert,int cert_length,
SECItem *issuer, SECItem *serial, SECItem *derSN, SECItem *subject,
SECItem *valid, SECItem *subjkey)
{
unsigned char *buf;
unsigned int buf_length;
unsigned char *dummy;
unsigned int dummylen;
/* get past the signature wrap */
buf = nsslowcert_dataStart(cert,cert_length,&buf_length,PR_FALSE, NULL);
if (buf == NULL) return SECFailure;
/* get into the raw cert data */
buf = nsslowcert_dataStart(buf,buf_length,&buf_length,PR_FALSE, NULL);
if (buf == NULL) return SECFailure;
/* skip past any optional version number */
if ((buf[0] & 0xa0) == 0xa0) {
dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL);
if (dummy == NULL) return SECFailure;
buf_length -= (dummy-buf) + dummylen;
buf = dummy + dummylen;
}
/* serial number */
if (derSN) {
derSN->data=nsslowcert_dataStart(buf,buf_length,&derSN->len,PR_TRUE, NULL);
}
serial->data = nsslowcert_dataStart(buf,buf_length,&serial->len,PR_FALSE, NULL);
if (serial->data == NULL) return SECFailure;
buf_length -= (serial->data-buf) + serial->len;
buf = serial->data + serial->len;
/* skip the OID */
dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL);
if (dummy == NULL) return SECFailure;
buf_length -= (dummy-buf) + dummylen;
buf = dummy + dummylen;
/* issuer */
issuer->data = nsslowcert_dataStart(buf,buf_length,&issuer->len,PR_TRUE, NULL);
if (issuer->data == NULL) return SECFailure;
buf_length -= (issuer->data-buf) + issuer->len;
buf = issuer->data + issuer->len;
/* only wanted issuer/SN */
if (valid == NULL) {
return SECSuccess;
}
/* validity */
valid->data = nsslowcert_dataStart(buf,buf_length,&valid->len,PR_FALSE, NULL);
if (valid->data == NULL) return SECFailure;
buf_length -= (valid->data-buf) + valid->len;
buf = valid->data + valid->len;
/*subject */
subject->data=nsslowcert_dataStart(buf,buf_length,&subject->len,PR_TRUE, NULL);
if (subject->data == NULL) return SECFailure;
buf_length -= (subject->data-buf) + subject->len;
buf = subject->data + subject->len;
/* subject key info */
subjkey->data=nsslowcert_dataStart(buf,buf_length,&subjkey->len,PR_TRUE, NULL);
if (subjkey->data == NULL) return SECFailure;
buf_length -= (subjkey->data-buf) + subjkey->len;
buf = subjkey->data + subjkey->len;
return SECSuccess;
}
SECStatus
nsslowcert_GetCertTimes(NSSLOWCERTCertificate *c, PRTime *notBefore, PRTime *notAfter)
{
int rv;
NSSLOWCERTValidity validity;
rv = nsslowcert_GetValidityFields(c->validity.data,c->validity.len,
&validity.notBefore,&validity.notAfter);
if (rv != SECSuccess) {
return rv;
}
/* convert DER not-before time */
rv = DER_DecodeTimeChoice(notBefore, &validity.notBefore);
if (rv) {
return(SECFailure);
}
/* convert DER not-after time */
rv = DER_DecodeTimeChoice(notAfter, &validity.notAfter);
if (rv) {
return(SECFailure);
}
return(SECSuccess);
}
/*
* is certa newer than certb? If one is expired, pick the other one.
*/
PRBool
nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb)
{
PRTime notBeforeA, notAfterA, notBeforeB, notAfterB, now;
SECStatus rv;
PRBool newerbefore, newerafter;
rv = nsslowcert_GetCertTimes(certa, &notBeforeA, &notAfterA);
if ( rv != SECSuccess ) {
return(PR_FALSE);
}
rv = nsslowcert_GetCertTimes(certb, &notBeforeB, &notAfterB);
if ( rv != SECSuccess ) {
return(PR_TRUE);
}
newerbefore = PR_FALSE;
if ( LL_CMP(notBeforeA, >, notBeforeB) ) {
newerbefore = PR_TRUE;
}
newerafter = PR_FALSE;
if ( LL_CMP(notAfterA, >, notAfterB) ) {
newerafter = PR_TRUE;
}
if ( newerbefore && newerafter ) {
return(PR_TRUE);
}
if ( ( !newerbefore ) && ( !newerafter ) ) {
return(PR_FALSE);
}
/* get current time */
now = PR_Now();
if ( newerbefore ) {
/* cert A was issued after cert B, but expires sooner */
/* if A is expired, then pick B */
if ( LL_CMP(notAfterA, <, now ) ) {
return(PR_FALSE);
}
return(PR_TRUE);
} else {
/* cert B was issued after cert A, but expires sooner */
/* if B is expired, then pick A */
if ( LL_CMP(notAfterB, <, now ) ) {
return(PR_TRUE);
}
return(PR_FALSE);
}
}
#define SOFT_DEFAULT_CHUNKSIZE 2048
static SECStatus
nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena, SECItem *issuer, SECItem *sn,
SECItem *key)
{
unsigned int len = sn->len + issuer->len;
if (arena) {
key->data = (unsigned char*)PORT_ArenaAlloc(arena, len);
} else {
if (len > key->len) {
key->data = (unsigned char*)PORT_ArenaAlloc(arena, len);
}
}
if ( !key->data ) {
goto loser;
}
key->len = len;
/* copy the serialNumber */
PORT_Memcpy(key->data, sn->data, sn->len);
/* copy the issuer */
PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
return(SECSuccess);
loser:
return(SECFailure);
}
/*
* take a DER certificate and decode it into a certificate structure
*/
NSSLOWCERTCertificate *
nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname)
{
NSSLOWCERTCertificate *cert;
int rv;
/* allocate the certificate structure */
cert = nsslowcert_CreateCert();
if ( !cert ) {
goto loser;
}
/* point to passed in DER data */
cert->derCert = *derSignedCert;
cert->nickname = NULL;
cert->certKey.data = NULL;
cert->referenceCount = 1;
/* decode the certificate info */
rv = nsslowcert_GetCertFields(cert->derCert.data, cert->derCert.len,
&cert->derIssuer, &cert->serialNumber, &cert->derSN, &cert->derSubject,
&cert->validity, &cert->derSubjKeyInfo);
/* cert->subjectKeyID; x509v3 subject key identifier */
cert->subjectKeyID.data = NULL;
cert->subjectKeyID.len = 0;
cert->dbEntry = NULL;
cert ->trust = NULL;
/* generate and save the database key for the cert */
cert->certKey.data = cert->certKeySpace;
cert->certKey.len = sizeof(cert->certKeySpace);
rv = nsslowcert_KeyFromIssuerAndSN(NULL, &cert->derIssuer,
&cert->serialNumber, &cert->certKey);
if ( rv ) {
goto loser;
}
/* set the nickname */
if ( nickname == NULL ) {
cert->nickname = NULL;
} else {
/* copy and install the nickname */
cert->nickname = pkcs11_copyNickname(nickname,cert->nicknameSpace,
sizeof(cert->nicknameSpace));
}
#ifdef FIXME
/* initialize the subjectKeyID */
rv = cert_GetKeyID(cert);
if ( rv != SECSuccess ) {
goto loser;
}
/* set the email address */
cert->emailAddr = CERT_GetCertificateEmailAddress(cert);
#endif
cert->referenceCount = 1;
return(cert);
loser:
if (cert) {
nsslowcert_DestroyCertificate(cert);
}
return(0);
}
char *
nsslowcert_FixupEmailAddr(char *emailAddr)
{
char *retaddr;
char *str;
if ( emailAddr == NULL ) {
return(NULL);
}
/* copy the string */
str = retaddr = PORT_Strdup(emailAddr);
if ( str == NULL ) {
return(NULL);
}
/* make it lower case */
while ( *str ) {
*str = tolower( *str );
str++;
}
return(retaddr);
}
/*
* Generate a database key, based on serial number and issuer, from a
* DER certificate.
*/
SECStatus
nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key)
{
int rv;
NSSLOWCERTCertKey certkey;
PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey));
rv = nsslowcert_GetCertFields(derCert->data, derCert->len,
&certkey.derIssuer, &certkey.serialNumber, NULL, NULL, NULL, NULL);
if ( rv ) {
goto loser;
}
return(nsslowcert_KeyFromIssuerAndSN(arena, &certkey.derIssuer,
&certkey.serialNumber, key));
loser:
return(SECFailure);
}
NSSLOWKEYPublicKey *
nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
{
NSSLOWCERTSubjectPublicKeyInfo spki;
NSSLOWKEYPublicKey *pubk;
SECItem os;
SECStatus rv;
PRArenaPool *arena;
SECOidTag tag;
SECItem newDerSubjKeyInfo;
arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
if (arena == NULL)
return NULL;
pubk = (NSSLOWKEYPublicKey *)
PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYPublicKey));
if (pubk == NULL) {
PORT_FreeArena (arena, PR_FALSE);
return NULL;
}
pubk->arena = arena;
PORT_Memset(&spki,0,sizeof(spki));
/* copy the DER into the arena, since Quick DER returns data that points
into the DER input, which may get freed by the caller */
rv = SECITEM_CopyItem(arena, &newDerSubjKeyInfo, &cert->derSubjKeyInfo);
if ( rv != SECSuccess ) {
PORT_FreeArena (arena, PR_FALSE);
return NULL;
}
/* we haven't bothered decoding the spki struct yet, do it now */
rv = SEC_QuickDERDecodeItem(arena, &spki,
nsslowcert_SubjectPublicKeyInfoTemplate, &newDerSubjKeyInfo);
if (rv != SECSuccess) {
PORT_FreeArena (arena, PR_FALSE);
return NULL;
}
/* Convert bit string length from bits to bytes */
os = spki.subjectPublicKey;
DER_ConvertBitString (&os);
tag = SECOID_GetAlgorithmTag(&spki.algorithm);
switch ( tag ) {
case SEC_OID_X500_RSA_ENCRYPTION:
case SEC_OID_PKCS1_RSA_ENCRYPTION:
pubk->keyType = NSSLOWKEYRSAKey;
prepare_low_rsa_pub_key_for_asn1(pubk);
rv = SEC_QuickDERDecodeItem(arena, pubk,
nsslowcert_RSAPublicKeyTemplate, &os);
if (rv == SECSuccess)
return pubk;
break;
case SEC_OID_ANSIX9_DSA_SIGNATURE:
pubk->keyType = NSSLOWKEYDSAKey;
prepare_low_dsa_pub_key_for_asn1(pubk);
rv = SEC_QuickDERDecodeItem(arena, pubk,
nsslowcert_DSAPublicKeyTemplate, &os);
if (rv == SECSuccess) return pubk;
break;
case SEC_OID_X942_DIFFIE_HELMAN_KEY:
pubk->keyType = NSSLOWKEYDHKey;
prepare_low_dh_pub_key_for_asn1(pubk);
rv = SEC_QuickDERDecodeItem(arena, pubk,
nsslowcert_DHPublicKeyTemplate, &os);
if (rv == SECSuccess) return pubk;
break;
#ifdef NSS_ENABLE_ECC
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
pubk->keyType = NSSLOWKEYECKey;
/* Since PKCS#11 directly takes the DER encoding of EC params
* and public value, we don't need any decoding here.
*/
rv = SECITEM_CopyItem(arena, &pubk->u.ec.ecParams.DEREncoding,
&spki.algorithm.parameters);
if ( rv != SECSuccess )
break;
/* Fill out the rest of the ecParams structure
* based on the encoded params
*/
if (EC_FillParams(arena, &pubk->u.ec.ecParams.DEREncoding,
&pubk->u.ec.ecParams) != SECSuccess)
break;
rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &os);
if (rv == SECSuccess) return pubk;
break;
#endif /* NSS_ENABLE_ECC */
default:
rv = SECFailure;
break;
}
nsslowkey_DestroyPublicKey (pubk);
return NULL;
}

View File

@@ -1,492 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "lowkeyi.h"
#include "secoid.h"
#include "secitem.h"
#include "secder.h"
#include "base64.h"
#include "secasn1.h"
#include "pcert.h"
#include "secerr.h"
#ifdef NSS_ENABLE_ECC
extern SECStatus EC_CopyParams(PRArenaPool *arena,
ECParams *dstParams,
const ECParams *srcParams);
#endif
const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
{ SEC_ASN1_INTEGER, offsetof(PQGParams,prime) },
{ SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) },
{ SEC_ASN1_INTEGER, offsetof(PQGParams,base) },
{ 0, }
};
const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.version) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.modulus) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.publicExponent) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.privateExponent) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime1) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime2) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent1) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent2) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.coefficient) },
{ 0 }
};
const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.publicValue) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
{ 0, }
};
const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = {
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
};
const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.publicValue) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.privateValue) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.base) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.prime) },
{ 0, }
};
#ifdef NSS_ENABLE_ECC
/* XXX This is just a placeholder for later when we support
* generic curves and need full-blown support for parsing EC
* parameters. For now, we only support named curves in which
* EC params are simply encoded as an object ID and we don't
* use nsslowkey_ECParamsTemplate.
*/
const SEC_ASN1Template nsslowkey_ECParamsTemplate[] = {
{ SEC_ASN1_CHOICE, offsetof(ECParams,type), NULL, sizeof(ECParams) },
{ SEC_ASN1_OBJECT_ID, offsetof(ECParams,curveOID), NULL, ec_params_named },
{ 0, }
};
/* NOTE: The SECG specification allows the private key structure
* to contain curve parameters but recommends that they be stored
* in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
* instead.
*/
const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
{ SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.ec.version) },
{ SEC_ASN1_OCTET_STRING,
offsetof(NSSLOWKEYPrivateKey,u.ec.privateValue) },
/* XXX The following template works for now since we only
* support named curves for which the parameters are
* encoded as an object ID. When we support generic curves,
* we'll need to define nsslowkey_ECParamsTemplate
*/
#if 1
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0,
offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams.curveOID),
SEC_ObjectIDTemplate },
#else
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0,
offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams),
nsslowkey_ECParamsTemplate },
#endif
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 1,
offsetof(NSSLOWKEYPrivateKey,u.ec.publicValue),
SEC_BitStringTemplate },
{ 0, }
};
#endif /* NSS_ENABLE_ECC */
/*
* See bugzilla bug 125359
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
* all of the templates above that en/decode into integers must be converted
* from ASN.1's signed integer type. This is done by marking either the
* source or destination (encoding or decoding, respectively) type as
* siUnsignedInteger.
*/
void
prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
{
key->u.rsa.modulus.type = siUnsignedInteger;
key->u.rsa.publicExponent.type = siUnsignedInteger;
key->u.rsa.privateExponent.type = siUnsignedInteger;
key->u.rsa.prime1.type = siUnsignedInteger;
key->u.rsa.prime2.type = siUnsignedInteger;
key->u.rsa.exponent1.type = siUnsignedInteger;
key->u.rsa.exponent2.type = siUnsignedInteger;
key->u.rsa.coefficient.type = siUnsignedInteger;
}
void
prepare_low_pqg_params_for_asn1(PQGParams *params)
{
params->prime.type = siUnsignedInteger;
params->subPrime.type = siUnsignedInteger;
params->base.type = siUnsignedInteger;
}
void
prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
{
key->u.dsa.publicValue.type = siUnsignedInteger;
key->u.dsa.privateValue.type = siUnsignedInteger;
key->u.dsa.params.prime.type = siUnsignedInteger;
key->u.dsa.params.subPrime.type = siUnsignedInteger;
key->u.dsa.params.base.type = siUnsignedInteger;
}
void
prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key)
{
key->u.dsa.privateValue.type = siUnsignedInteger;
}
void
prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
{
key->u.dh.prime.type = siUnsignedInteger;
key->u.dh.base.type = siUnsignedInteger;
key->u.dh.publicValue.type = siUnsignedInteger;
key->u.dh.privateValue.type = siUnsignedInteger;
}
#ifdef NSS_ENABLE_ECC
void
prepare_low_ecparams_for_asn1(ECParams *params)
{
params->DEREncoding.type = siUnsignedInteger;
params->curveOID.type = siUnsignedInteger;
}
void
prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
{
key->u.ec.version.type = siUnsignedInteger;
key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger;
key->u.ec.ecParams.curveOID.type = siUnsignedInteger;
key->u.ec.privateValue.type = siUnsignedInteger;
key->u.ec.publicValue.type = siUnsignedInteger;
}
#endif /* NSS_ENABLE_ECC */
void
nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
{
if (privk && privk->arena) {
PORT_FreeArena(privk->arena, PR_TRUE);
}
}
void
nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
{
if (pubk && pubk->arena) {
PORT_FreeArena(pubk->arena, PR_FALSE);
}
}
unsigned
nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
{
unsigned char b0;
/* interpret modulus length as key strength... in
* fortezza that's the public key length */
switch (pubk->keyType) {
case NSSLOWKEYRSAKey:
b0 = pubk->u.rsa.modulus.data[0];
return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
default:
break;
}
return 0;
}
unsigned
nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk)
{
unsigned char b0;
switch (privk->keyType) {
case NSSLOWKEYRSAKey:
b0 = privk->u.rsa.modulus.data[0];
return b0 ? privk->u.rsa.modulus.len : privk->u.rsa.modulus.len - 1;
default:
break;
}
return 0;
}
NSSLOWKEYPublicKey *
nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
{
NSSLOWKEYPublicKey *pubk;
PLArenaPool *arena;
arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) {
PORT_SetError (SEC_ERROR_NO_MEMORY);
return NULL;
}
switch(privk->keyType) {
case NSSLOWKEYRSAKey:
case NSSLOWKEYNullKey:
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
sizeof (NSSLOWKEYPublicKey));
if (pubk != NULL) {
SECStatus rv;
pubk->arena = arena;
pubk->keyType = privk->keyType;
if (privk->keyType == NSSLOWKEYNullKey) return pubk;
rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
&privk->u.rsa.modulus);
if (rv == SECSuccess) {
rv = SECITEM_CopyItem (arena, &pubk->u.rsa.publicExponent,
&privk->u.rsa.publicExponent);
if (rv == SECSuccess)
return pubk;
}
nsslowkey_DestroyPublicKey (pubk);
} else {
PORT_SetError (SEC_ERROR_NO_MEMORY);
}
break;
case NSSLOWKEYDSAKey:
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
sizeof(NSSLOWKEYPublicKey));
if (pubk != NULL) {
SECStatus rv;
pubk->arena = arena;
pubk->keyType = privk->keyType;
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
&privk->u.dsa.publicValue);
if (rv != SECSuccess) break;
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
&privk->u.dsa.params.prime);
if (rv != SECSuccess) break;
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
&privk->u.dsa.params.subPrime);
if (rv != SECSuccess) break;
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
&privk->u.dsa.params.base);
if (rv == SECSuccess) return pubk;
}
break;
case NSSLOWKEYDHKey:
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
sizeof(NSSLOWKEYPublicKey));
if (pubk != NULL) {
SECStatus rv;
pubk->arena = arena;
pubk->keyType = privk->keyType;
rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
&privk->u.dh.publicValue);
if (rv != SECSuccess) break;
rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
&privk->u.dh.prime);
if (rv != SECSuccess) break;
rv = SECITEM_CopyItem(arena, &pubk->u.dh.base,
&privk->u.dh.base);
if (rv == SECSuccess) return pubk;
}
break;
#ifdef NSS_ENABLE_ECC
case NSSLOWKEYECKey:
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
sizeof(NSSLOWKEYPublicKey));
if (pubk != NULL) {
SECStatus rv;
pubk->arena = arena;
pubk->keyType = privk->keyType;
rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue,
&privk->u.ec.publicValue);
if (rv != SECSuccess) break;
pubk->u.ec.ecParams.arena = arena;
/* Copy the rest of the params */
rv = EC_CopyParams(arena, &(pubk->u.ec.ecParams),
&(privk->u.ec.ecParams));
if (rv == SECSuccess) return pubk;
}
break;
#endif /* NSS_ENABLE_ECC */
/* No Fortezza in Low Key implementations (Fortezza keys aren't
* stored in our data base */
default:
break;
}
PORT_FreeArena (arena, PR_FALSE);
return NULL;
}
NSSLOWKEYPrivateKey *
nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey)
{
NSSLOWKEYPrivateKey *returnKey = NULL;
SECStatus rv = SECFailure;
PLArenaPool *poolp;
if(!privKey) {
return NULL;
}
poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if(!poolp) {
return NULL;
}
returnKey = (NSSLOWKEYPrivateKey*)PORT_ArenaZAlloc(poolp, sizeof(NSSLOWKEYPrivateKey));
if(!returnKey) {
rv = SECFailure;
goto loser;
}
returnKey->keyType = privKey->keyType;
returnKey->arena = poolp;
switch(privKey->keyType) {
case NSSLOWKEYRSAKey:
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.modulus),
&(privKey->u.rsa.modulus));
if(rv != SECSuccess) break;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.version),
&(privKey->u.rsa.version));
if(rv != SECSuccess) break;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.publicExponent),
&(privKey->u.rsa.publicExponent));
if(rv != SECSuccess) break;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.privateExponent),
&(privKey->u.rsa.privateExponent));
if(rv != SECSuccess) break;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime1),
&(privKey->u.rsa.prime1));
if(rv != SECSuccess) break;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime2),
&(privKey->u.rsa.prime2));
if(rv != SECSuccess) break;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent1),
&(privKey->u.rsa.exponent1));
if(rv != SECSuccess) break;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent2),
&(privKey->u.rsa.exponent2));
if(rv != SECSuccess) break;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.coefficient),
&(privKey->u.rsa.coefficient));
if(rv != SECSuccess) break;
break;
case NSSLOWKEYDSAKey:
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.publicValue),
&(privKey->u.dsa.publicValue));
if(rv != SECSuccess) break;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.privateValue),
&(privKey->u.dsa.privateValue));
if(rv != SECSuccess) break;
returnKey->u.dsa.params.arena = poolp;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.prime),
&(privKey->u.dsa.params.prime));
if(rv != SECSuccess) break;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.subPrime),
&(privKey->u.dsa.params.subPrime));
if(rv != SECSuccess) break;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.base),
&(privKey->u.dsa.params.base));
if(rv != SECSuccess) break;
break;
case NSSLOWKEYDHKey:
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.publicValue),
&(privKey->u.dh.publicValue));
if(rv != SECSuccess) break;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.privateValue),
&(privKey->u.dh.privateValue));
if(rv != SECSuccess) break;
returnKey->u.dsa.params.arena = poolp;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.prime),
&(privKey->u.dh.prime));
if(rv != SECSuccess) break;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.base),
&(privKey->u.dh.base));
if(rv != SECSuccess) break;
break;
#ifdef NSS_ENABLE_ECC
case NSSLOWKEYECKey:
rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.version),
&(privKey->u.ec.version));
if(rv != SECSuccess) break;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.publicValue),
&(privKey->u.ec.publicValue));
if(rv != SECSuccess) break;
rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.privateValue),
&(privKey->u.ec.privateValue));
if(rv != SECSuccess) break;
returnKey->u.ec.ecParams.arena = poolp;
/* Copy the rest of the params */
rv = EC_CopyParams(poolp, &(returnKey->u.ec.ecParams),
&(privKey->u.ec.ecParams));
if (rv != SECSuccess) break;
break;
#endif /* NSS_ENABLE_ECC */
default:
rv = SECFailure;
}
loser:
if(rv != SECSuccess) {
PORT_FreeArena(poolp, PR_TRUE);
returnKey = NULL;
}
return returnKey;
}

View File

@@ -1,274 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: lowkeyi.h,v 1.10 2004-04-27 23:04:38 gerv%gerv.net Exp $ */
#ifndef _LOWKEYI_H_
#define _LOWKEYI_H_
#include "prtypes.h"
#include "seccomon.h"
#include "secoidt.h"
#include "pcertt.h"
#include "lowkeyti.h"
SEC_BEGIN_PROTOS
/*
* See bugzilla bug 125359
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
* all of the templates above that en/decode into integers must be converted
* from ASN.1's signed integer type. This is done by marking either the
* source or destination (encoding or decoding, respectively) type as
* siUnsignedInteger.
*/
extern void prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
extern void prepare_low_pqg_params_for_asn1(PQGParams *params);
extern void prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
extern void prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key);
extern void prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
#ifdef NSS_ENABLE_ECC
extern void prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key);
extern void prepare_low_ecparams_for_asn1(ECParams *params);
#endif /* NSS_ENABLE_ECC */
typedef char * (* NSSLOWKEYDBNameFunc)(void *arg, int dbVersion);
/*
** Open a key database.
*/
extern NSSLOWKEYDBHandle *nsslowkey_OpenKeyDB(PRBool readOnly,
const char *domain,
const char *prefix,
NSSLOWKEYDBNameFunc namecb,
void *cbarg);
/*
* Clear out all the keys in the existing database
*/
extern SECStatus nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle);
/*
** Close the specified key database.
*/
extern void nsslowkey_CloseKeyDB(NSSLOWKEYDBHandle *handle);
/*
* Get the version number of the database
*/
extern int nsslowkey_GetKeyDBVersion(NSSLOWKEYDBHandle *handle);
/*
** Support a default key database.
*/
extern void nsslowkey_SetDefaultKeyDB(NSSLOWKEYDBHandle *handle);
extern NSSLOWKEYDBHandle *nsslowkey_GetDefaultKeyDB(void);
/* set the alg id of the key encryption algorithm */
extern void nsslowkey_SetDefaultKeyDBAlg(SECOidTag alg);
/*
* given a password and salt, produce a hash of the password
*/
extern SECItem *nsslowkey_HashPassword(char *pw, SECItem *salt);
/*
* Derive the actual password value for a key database from the
* password string value. The derivation uses global salt value
* stored in the key database.
*/
extern SECItem *
nsslowkey_DeriveKeyDBPassword(NSSLOWKEYDBHandle *handle, char *pw);
/*
** Delete a key from the database
*/
extern SECStatus nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle,
SECItem *pubkey);
/*
** Store a key in the database, indexed by its public key modulus.
** "pk" is the private key to store
** "f" is a the callback function for getting the password
** "arg" is the argument for the callback
*/
extern SECStatus nsslowkey_StoreKeyByPublicKey(NSSLOWKEYDBHandle *handle,
NSSLOWKEYPrivateKey *pk,
SECItem *pubKeyData,
char *nickname,
SECItem *arg);
/* does the key for this cert exist in the database filed by modulus */
extern PRBool nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle,
NSSLOWCERTCertificate *cert);
/* does a key with this ID already exist? */
extern PRBool nsslowkey_KeyForIDExists(NSSLOWKEYDBHandle *handle, SECItem *id);
extern SECStatus nsslowkey_HasKeyDBPassword(NSSLOWKEYDBHandle *handle);
extern SECStatus nsslowkey_SetKeyDBPassword(NSSLOWKEYDBHandle *handle,
SECItem *pwitem);
extern SECStatus nsslowkey_CheckKeyDBPassword(NSSLOWKEYDBHandle *handle,
SECItem *pwitem);
extern SECStatus nsslowkey_ChangeKeyDBPassword(NSSLOWKEYDBHandle *handle,
SECItem *oldpwitem,
SECItem *newpwitem);
/*
** Destroy a private key object.
** "key" the object
** "freeit" if PR_TRUE then free the object as well as its sub-objects
*/
extern void nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *key);
/*
** Destroy a public key object.
** "key" the object
** "freeit" if PR_TRUE then free the object as well as its sub-objects
*/
extern void nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *key);
/*
** Return the modulus length of "pubKey".
*/
extern unsigned int nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubKey);
/*
** Return the modulus length of "privKey".
*/
extern unsigned int nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privKey);
/*
** Convert a low private key "privateKey" into a public low key
*/
extern NSSLOWKEYPublicKey
*nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privateKey);
/*
* Set the Key Database password.
* handle is a handle to the key database
* pwitem is the new password
* algorithm is the algorithm by which the key database
* password is to be encrypted.
* On failure, SECFailure is returned, otherwise SECSuccess is
* returned.
*/
extern SECStatus
nsslowkey_SetKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
SECItem *pwitem,
SECOidTag algorithm);
/* Check the key database password.
* handle is a handle to the key database
* pwitem is the suspect password
* algorithm is the algorithm by which the key database
* password is to be encrypted.
* The password is checked against plaintext to see if it is the
* actual password. If it is not, SECFailure is returned.
*/
extern SECStatus
nsslowkey_CheckKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
SECItem *pwitem,
SECOidTag algorithm);
/* Change the key database password and/or algorithm by which
* the password is stored with.
* handle is a handle to the key database
* old_pwitem is the current password
* new_pwitem is the new password
* old_algorithm is the algorithm by which the key database
* password is currently encrypted.
* new_algorithm is the algorithm with which the new password
* is to be encrypted.
* A return of anything but SECSuccess indicates failure.
*/
extern SECStatus
nsslowkey_ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
SECItem *oldpwitem, SECItem *newpwitem,
SECOidTag old_algorithm);
SECStatus
nsslowkey_UpdateNickname(NSSLOWKEYDBHandle *handle,
NSSLOWKEYPrivateKey *privkey,
SECItem *pubKeyData,
char *nickname,
SECItem *arg);
/* Store key by modulus and specify an encryption algorithm to use.
* handle is the pointer to the key database,
* privkey is the private key to be stored,
* f and arg are the function and arguments to the callback
* to get a password,
* algorithm is the algorithm which the privKey is to be stored.
* A return of anything but SECSuccess indicates failure.
*/
extern SECStatus
nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle,
NSSLOWKEYPrivateKey *privkey,
SECItem *pubKeyData,
char *nickname,
SECItem *arg,
SECOidTag algorithm,
PRBool update);
/* Find key by modulus. This function is the inverse of store key
* by modulus. An attempt to locate the key with "modulus" is
* performed. If the key is found, the private key is returned,
* else NULL is returned.
* modulus is the modulus to locate
*/
extern NSSLOWKEYPrivateKey *
nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus,
SECItem *arg);
extern char *
nsslowkey_FindKeyNicknameByPublicKey(NSSLOWKEYDBHandle *handle,
SECItem *modulus, SECItem *pwitem);
/* Make a copy of a low private key in it's own arena.
* a return of NULL indicates an error.
*/
extern NSSLOWKEYPrivateKey *
nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey);
SEC_END_PROTOS
#endif /* _LOWKEYI_H_ */

View File

@@ -1,163 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _LOWKEYTI_H_
#define _LOWKEYTI_H_ 1
#include "blapit.h"
#include "prtypes.h"
#include "plarena.h"
#include "secitem.h"
#include "secasn1t.h"
#include "secoidt.h"
/*#include "secmodt.h"
#include "pkcs11t.h" */
/*
* a key in/for the data base
*/
struct NSSLOWKEYDBKeyStr {
PLArenaPool *arena;
int version;
char *nickname;
SECItem salt;
SECItem derPK;
};
typedef struct NSSLOWKEYDBKeyStr NSSLOWKEYDBKey;
typedef struct NSSLOWKEYDBHandleStr NSSLOWKEYDBHandle;
#ifdef NSS_USE_KEY4_DB
#define NSSLOWKEY_DB_FILE_VERSION 4
#else
#define NSSLOWKEY_DB_FILE_VERSION 3
#endif
#define NSSLOWKEY_VERSION 0 /* what we *create* */
/*
** Typedef for callback to get a password "key".
*/
extern const SEC_ASN1Template nsslowkey_PQGParamsTemplate[];
extern const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[];
extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[];
extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[];
extern const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[];
extern const SEC_ASN1Template nsslowkey_DHPrivateKeyExportTemplate[];
#ifdef NSS_ENABLE_ECC
#define NSSLOWKEY_EC_PRIVATE_KEY_VERSION 1 /* as per SECG 1 C.4 */
extern const SEC_ASN1Template nsslowkey_ECParamsTemplate[];
extern const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[];
#endif /* NSS_ENABLE_ECC */
extern const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[];
extern const SEC_ASN1Template nsslowkey_EncryptedPrivateKeyInfoTemplate[];
/*
* PKCS #8 attributes
*/
struct NSSLOWKEYAttributeStr {
SECItem attrType;
SECItem *attrValue;
};
typedef struct NSSLOWKEYAttributeStr NSSLOWKEYAttribute;
/*
** A PKCS#8 private key info object
*/
struct NSSLOWKEYPrivateKeyInfoStr {
PLArenaPool *arena;
SECItem version;
SECAlgorithmID algorithm;
SECItem privateKey;
NSSLOWKEYAttribute **attributes;
};
typedef struct NSSLOWKEYPrivateKeyInfoStr NSSLOWKEYPrivateKeyInfo;
#define NSSLOWKEY_PRIVATE_KEY_INFO_VERSION 0 /* what we *create* */
/*
** A PKCS#8 private key info object
*/
struct NSSLOWKEYEncryptedPrivateKeyInfoStr {
PLArenaPool *arena;
SECAlgorithmID algorithm;
SECItem encryptedData;
};
typedef struct NSSLOWKEYEncryptedPrivateKeyInfoStr NSSLOWKEYEncryptedPrivateKeyInfo;
typedef enum {
NSSLOWKEYNullKey = 0,
NSSLOWKEYRSAKey = 1,
NSSLOWKEYDSAKey = 2,
NSSLOWKEYDHKey = 4,
NSSLOWKEYECKey = 5
} NSSLOWKEYType;
/*
** An RSA public key object.
*/
struct NSSLOWKEYPublicKeyStr {
PLArenaPool *arena;
NSSLOWKEYType keyType ;
union {
RSAPublicKey rsa;
DSAPublicKey dsa;
DHPublicKey dh;
ECPublicKey ec;
} u;
};
typedef struct NSSLOWKEYPublicKeyStr NSSLOWKEYPublicKey;
/*
** Low Level private key object
** This is only used by the raw Crypto engines (crypto), keydb (keydb),
** and PKCS #11. Everyone else uses the high level key structure.
*/
struct NSSLOWKEYPrivateKeyStr {
PLArenaPool *arena;
NSSLOWKEYType keyType;
union {
RSAPrivateKey rsa;
DSAPrivateKey dsa;
DHPrivateKey dh;
ECPrivateKey ec;
} u;
};
typedef struct NSSLOWKEYPrivateKeyStr NSSLOWKEYPrivateKey;
#endif /* _LOWKEYTI_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,135 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _SECPKCS5_H_
#define _SECPKCS5_H_
#include "plarena.h"
#include "secitem.h"
#include "seccomon.h"
#include "secoidt.h"
#include "hasht.h"
typedef SECItem * (* SEC_PKCS5GetPBEPassword)(void *arg);
/* used for V2 PKCS 12 Draft Spec */
typedef enum {
pbeBitGenIDNull = 0,
pbeBitGenCipherKey = 0x01,
pbeBitGenCipherIV = 0x02,
pbeBitGenIntegrityKey = 0x03
} PBEBitGenID;
typedef enum {
NSSPKCS5_PBKDF1 = 0,
NSSPKCS5_PBKDF2 = 1,
NSSPKCS5_PKCS12_V2 = 2
} NSSPKCS5PBEType;
typedef struct NSSPKCS5PBEParameterStr NSSPKCS5PBEParameter;
struct NSSPKCS5PBEParameterStr {
PRArenaPool *poolp;
SECItem salt; /* octet string */
SECItem iteration; /* integer */
/* used locally */
int iter;
int keyLen;
int ivLen;
HASH_HashType hashType;
NSSPKCS5PBEType pbeType;
PBEBitGenID keyID;
SECOidTag encAlg;
PRBool is2KeyDES;
};
SEC_BEGIN_PROTOS
/* Create a PKCS5 Algorithm ID
* The algorithm ID is set up using the PKCS #5 parameter structure
* algorithm is the PBE algorithm ID for the desired algorithm
* pbe is a pbe param block with all the info needed to create the
* algorithm id.
* If an error occurs or the algorithm specified is not supported
* or is not a password based encryption algorithm, NULL is returned.
* Otherwise, a pointer to the algorithm id is returned.
*/
extern SECAlgorithmID *
nsspkcs5_CreateAlgorithmID(PRArenaPool *arena, SECOidTag algorithm,
NSSPKCS5PBEParameter *pbe);
/*
* Convert an Algorithm ID to a PBE Param.
* NOTE: this does not suppport PKCS 5 v2 because it's only used for the
* keyDB which only support PKCS 5 v1, PFX, and PKCS 12.
*/
NSSPKCS5PBEParameter *
nsspkcs5_AlgidToParam(SECAlgorithmID *algid);
/*
* Convert an Algorithm ID to a PBE Param.
* NOTE: this does not suppport PKCS 5 v2 because it's only used for the
* keyDB which only support PKCS 5 v1, PFX, and PKCS 12.
*/
NSSPKCS5PBEParameter *
nsspkcs5_NewParam(SECOidTag alg, SECItem *salt, int iterator);
/* Encrypt/Decrypt data using password based encryption.
* algid is the PBE algorithm identifier,
* pwitem is the password,
* src is the source for encryption/decryption,
* encrypt is PR_TRUE for encryption, PR_FALSE for decryption.
* The key and iv are generated based upon PKCS #5 then the src
* is either encrypted or decrypted. If an error occurs, NULL
* is returned, otherwise the ciphered contents is returned.
*/
extern SECItem *
nsspkcs5_CipherData(NSSPKCS5PBEParameter *, SECItem *pwitem,
SECItem *src, PRBool encrypt, PRBool *update);
extern SECItem *
nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *, SECItem *pwitem,
SECItem *iv, PRBool faulty3DES);
/* Destroys PBE parameter */
extern void
nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *param);
SEC_END_PROTOS
#endif

View File

@@ -1,89 +0,0 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Netscape security libraries.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1994-2000
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
CORE_DEPTH = ../../..
MODULE = nss
REQUIRES = dbm
LIBRARY_NAME = softokn
LIBRARY_VERSION = 3
MAPFILE = $(OBJDIR)/softokn.def
DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DSOFTOKEN_LIB_NAME=\"$(notdir $(SHARED_LIBRARY))\"
EXPORTS = \
pkcs11.h \
pkcs11f.h \
pkcs11p.h \
pkcs11t.h \
pkcs11n.h \
pkcs11u.h \
$(NULL)
PRIVATE_EXPORTS = \
pk11pars.h \
$(NULL)
CSRCS = \
alghmac.c \
dbinit.c \
dbmshim.c \
ecdecode.c \
fipstest.c \
fipstokn.c \
keydb.c \
lowcert.c \
lowkey.c \
lowpbe.c \
padbuf.c \
pcertdb.c \
pk11db.c \
pkcs11.c \
pkcs11c.c \
pkcs11u.c \
rawhash.c \
rsawrapr.c \
softkver.c \
tlsprf.c \
$(NULL)
ifdef NSS_ENABLE_ECC
DEFINES += -DNSS_ENABLE_ECC
endif

View File

@@ -1,80 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "blapit.h"
#include "secport.h"
#include "secerr.h"
/*
* Prepare a buffer for DES encryption, growing to the appropriate boundary,
* filling with the appropriate padding.
*
* NOTE: If arena is non-NULL, we re-allocate from there, otherwise
* we assume (and use) XP memory (re)allocation.
*/
unsigned char *
DES_PadBuffer(PRArenaPool *arena, unsigned char *inbuf, unsigned int inlen,
unsigned int *outlen)
{
unsigned char *outbuf;
unsigned int des_len;
unsigned int i;
unsigned char des_pad_len;
/*
* We need from 1 to DES_KEY_LENGTH bytes -- we *always* grow.
* The extra bytes contain the value of the length of the padding:
* if we have 2 bytes of padding, then the padding is "0x02, 0x02".
*/
des_len = (inlen + DES_KEY_LENGTH) & ~(DES_KEY_LENGTH - 1);
if (arena != NULL) {
outbuf = (unsigned char*)PORT_ArenaGrow (arena, inbuf, inlen, des_len);
} else {
outbuf = (unsigned char*)PORT_Realloc (inbuf, des_len);
}
if (outbuf == NULL) {
PORT_SetError (SEC_ERROR_NO_MEMORY);
return NULL;
}
des_pad_len = des_len - inlen;
for (i = inlen; i < des_len; i++)
outbuf[i] = des_pad_len;
*outlen = des_len;
return outbuf;
}

View File

@@ -1,246 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _PCERTDB_H_
#define _PCERTDB_H_
#include "plarena.h"
#include "prlong.h"
#include "pcertt.h"
SEC_BEGIN_PROTOS
/*
** Add a DER encoded certificate to the permanent database.
** "derCert" is the DER encoded certificate.
** "nickname" is the nickname to use for the cert
** "trust" is the trust parameters for the cert
*/
SECStatus nsslowcert_AddPermCert(NSSLOWCERTCertDBHandle *handle,
NSSLOWCERTCertificate *cert,
char *nickname, NSSLOWCERTCertTrust *trust);
SECStatus nsslowcert_AddPermNickname(NSSLOWCERTCertDBHandle *dbhandle,
NSSLOWCERTCertificate *cert, char *nickname);
SECStatus nsslowcert_DeletePermCertificate(NSSLOWCERTCertificate *cert);
typedef SECStatus (PR_CALLBACK * PermCertCallback)(NSSLOWCERTCertificate *cert,
SECItem *k, void *pdata);
/*
** Traverse the entire permanent database, and pass the certs off to a
** user supplied function.
** "certfunc" is the user function to call for each certificate
** "udata" is the user's data, which is passed through to "certfunc"
*/
SECStatus
nsslowcert_TraversePermCerts(NSSLOWCERTCertDBHandle *handle,
PermCertCallback certfunc,
void *udata );
PRBool
nsslowcert_CertDBKeyConflict(SECItem *derCert, NSSLOWCERTCertDBHandle *handle);
certDBEntryRevocation *
nsslowcert_FindCrlByKey(NSSLOWCERTCertDBHandle *handle,
SECItem *crlKey, PRBool isKRL);
SECStatus
nsslowcert_DeletePermCRL(NSSLOWCERTCertDBHandle *handle,SECItem *derName,
PRBool isKRL);
SECStatus
nsslowcert_AddCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl ,
SECItem *derKey, char *url, PRBool isKRL);
NSSLOWCERTCertDBHandle *nsslowcert_GetDefaultCertDB();
NSSLOWKEYPublicKey *nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *);
NSSLOWCERTCertificate *
nsslowcert_NewTempCertificate(NSSLOWCERTCertDBHandle *handle, SECItem *derCert,
char *nickname, PRBool isperm, PRBool copyDER);
NSSLOWCERTCertificate *
nsslowcert_DupCertificate(NSSLOWCERTCertificate *cert);
void nsslowcert_DestroyCertificate(NSSLOWCERTCertificate *cert);
void nsslowcert_DestroyTrust(NSSLOWCERTTrust *Trust);
/*
* Lookup a certificate in the databases without locking
* "certKey" is the database key to look for
*
* XXX - this should be internal, but pkcs 11 needs to call it during a
* traversal.
*/
NSSLOWCERTCertificate *
nsslowcert_FindCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey);
/*
* Lookup trust for a certificate in the databases without locking
* "certKey" is the database key to look for
*
* XXX - this should be internal, but pkcs 11 needs to call it during a
* traversal.
*/
NSSLOWCERTTrust *
nsslowcert_FindTrustByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey);
/*
** Generate a certificate key from the issuer and serialnumber, then look it
** up in the database. Return the cert if found.
** "issuerAndSN" is the issuer and serial number to look for
*/
extern NSSLOWCERTCertificate *
nsslowcert_FindCertByIssuerAndSN (NSSLOWCERTCertDBHandle *handle, NSSLOWCERTIssuerAndSN *issuerAndSN);
/*
** Generate a certificate key from the issuer and serialnumber, then look it
** up in the database. Return the cert if found.
** "issuerAndSN" is the issuer and serial number to look for
*/
extern NSSLOWCERTTrust *
nsslowcert_FindTrustByIssuerAndSN (NSSLOWCERTCertDBHandle *handle, NSSLOWCERTIssuerAndSN *issuerAndSN);
/*
** Find a certificate in the database by a DER encoded certificate
** "derCert" is the DER encoded certificate
*/
extern NSSLOWCERTCertificate *
nsslowcert_FindCertByDERCert(NSSLOWCERTCertDBHandle *handle, SECItem *derCert);
/* convert an email address to lower case */
char *nsslowcert_FixupEmailAddr(char *emailAddr);
/*
** Decode a DER encoded certificate into an NSSLOWCERTCertificate structure
** "derSignedCert" is the DER encoded signed certificate
** "copyDER" is true if the DER should be copied, false if the
** existing copy should be referenced
** "nickname" is the nickname to use in the database. If it is NULL
** then a temporary nickname is generated.
*/
extern NSSLOWCERTCertificate *
nsslowcert_DecodeDERCertificate (SECItem *derSignedCert, char *nickname);
SECStatus
nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key);
certDBEntrySMime *
nsslowcert_ReadDBSMimeEntry(NSSLOWCERTCertDBHandle *certHandle,
char *emailAddr);
void
nsslowcert_DestroyDBEntry(certDBEntry *entry);
SECStatus
nsslowcert_OpenCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly,
const char *domain, const char *prefix,
NSSLOWCERTDBNameFunc namecb, void *cbarg, PRBool openVolatile);
void
nsslowcert_ClosePermCertDB(NSSLOWCERTCertDBHandle *handle);
/*
* is certa newer than certb? If one is expired, pick the other one.
*/
PRBool
nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb);
SECStatus
nsslowcert_TraverseDBEntries(NSSLOWCERTCertDBHandle *handle,
certDBEntryType type,
SECStatus (* callback)(SECItem *data, SECItem *key,
certDBEntryType type, void *pdata),
void *udata );
SECStatus
nsslowcert_TraversePermCertsForSubject(NSSLOWCERTCertDBHandle *handle,
SECItem *derSubject,
NSSLOWCERTCertCallback cb, void *cbarg);
int
nsslowcert_NumPermCertsForSubject(NSSLOWCERTCertDBHandle *handle,
SECItem *derSubject);
SECStatus
nsslowcert_TraversePermCertsForNickname(NSSLOWCERTCertDBHandle *handle,
char *nickname, NSSLOWCERTCertCallback cb, void *cbarg);
int
nsslowcert_NumPermCertsForNickname(NSSLOWCERTCertDBHandle *handle,
char *nickname);
SECStatus
nsslowcert_GetCertTrust(NSSLOWCERTCertificate *cert,
NSSLOWCERTCertTrust *trust);
SECStatus
nsslowcert_SaveSMimeProfile(NSSLOWCERTCertDBHandle *dbhandle, char *emailAddr,
SECItem *derSubject, SECItem *emailProfile, SECItem *profileTime);
/*
* Change the trust attributes of a certificate and make them permanent
* in the database.
*/
SECStatus
nsslowcert_ChangeCertTrust(NSSLOWCERTCertDBHandle *handle,
NSSLOWCERTCertificate *cert, NSSLOWCERTCertTrust *trust);
PRBool
nsslowcert_needDBVerify(NSSLOWCERTCertDBHandle *handle);
void
nsslowcert_setDBVerify(NSSLOWCERTCertDBHandle *handle, PRBool value);
PRBool
nsslowcert_hasTrust(NSSLOWCERTCertTrust *trust);
void
nsslowcert_DestroyFreeLists(void);
void
nsslowcert_DestroyGlobalLocks(void);
void
pkcs11_freeNickname(char *nickname, char *space);
char *
pkcs11_copyNickname(char *nickname, char *space, int spaceLen);
void
pkcs11_freeStaticData(unsigned char *data, unsigned char *space);
unsigned char *
pkcs11_copyStaticData(unsigned char *data, int datalen, unsigned char *space,
int spaceLen);
NSSLOWCERTCertificate *
nsslowcert_CreateCert(void);
SEC_END_PROTOS
#endif /* _PCERTDB_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,446 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* certt.h - public data structures for the certificate library
*
* $Id: pcertt.h,v 1.13 2004-04-25 15:03:16 gerv%gerv.net Exp $
*/
#ifndef _PCERTT_H_
#define _PCERTT_H_
#include "prclist.h"
#include "pkcs11t.h"
#include "seccomon.h"
#include "secoidt.h"
#include "plarena.h"
#include "prcvar.h"
#include "nssilock.h"
#include "prio.h"
#include "prmon.h"
/* Non-opaque objects */
typedef struct NSSLOWCERTCertDBHandleStr NSSLOWCERTCertDBHandle;
typedef struct NSSLOWCERTCertKeyStr NSSLOWCERTCertKey;
typedef struct NSSLOWCERTTrustStr NSSLOWCERTTrust;
typedef struct NSSLOWCERTCertTrustStr NSSLOWCERTCertTrust;
typedef struct NSSLOWCERTCertificateStr NSSLOWCERTCertificate;
typedef struct NSSLOWCERTCertificateListStr NSSLOWCERTCertificateList;
typedef struct NSSLOWCERTIssuerAndSNStr NSSLOWCERTIssuerAndSN;
typedef struct NSSLOWCERTSignedDataStr NSSLOWCERTSignedData;
typedef struct NSSLOWCERTSubjectPublicKeyInfoStr NSSLOWCERTSubjectPublicKeyInfo;
typedef struct NSSLOWCERTValidityStr NSSLOWCERTValidity;
/*
** An X.509 validity object
*/
struct NSSLOWCERTValidityStr {
PRArenaPool *arena;
SECItem notBefore;
SECItem notAfter;
};
/*
* A serial number and issuer name, which is used as a database key
*/
struct NSSLOWCERTCertKeyStr {
SECItem serialNumber;
SECItem derIssuer;
};
/*
** A signed data object. Used to implement the "signed" macro used
** in the X.500 specs.
*/
struct NSSLOWCERTSignedDataStr {
SECItem data;
SECAlgorithmID signatureAlgorithm;
SECItem signature;
};
/*
** An X.509 subject-public-key-info object
*/
struct NSSLOWCERTSubjectPublicKeyInfoStr {
PRArenaPool *arena;
SECAlgorithmID algorithm;
SECItem subjectPublicKey;
};
typedef struct _certDBEntryCert certDBEntryCert;
typedef struct _certDBEntryRevocation certDBEntryRevocation;
struct NSSLOWCERTCertTrustStr {
unsigned int sslFlags;
unsigned int emailFlags;
unsigned int objectSigningFlags;
};
/*
** PKCS11 Trust representation
*/
struct NSSLOWCERTTrustStr {
NSSLOWCERTTrust *next;
NSSLOWCERTCertDBHandle *dbhandle;
SECItem dbKey; /* database key for this cert */
certDBEntryCert *dbEntry; /* database entry struct */
NSSLOWCERTCertTrust *trust;
SECItem *derCert; /* original DER for the cert */
unsigned char dbKeySpace[512];
};
/*
** An X.509 certificate object (the unsigned form)
*/
struct NSSLOWCERTCertificateStr {
/* the arena is used to allocate any data structures that have the same
* lifetime as the cert. This is all stuff that hangs off of the cert
* structure, and is all freed at the same time. I is used when the
* cert is decoded, destroyed, and at some times when it changes
* state
*/
NSSLOWCERTCertificate *next;
NSSLOWCERTCertDBHandle *dbhandle;
SECItem derCert; /* original DER for the cert */
SECItem derIssuer; /* DER for issuer name */
SECItem derSN;
SECItem serialNumber;
SECItem derSubject; /* DER for subject name */
SECItem derSubjKeyInfo;
NSSLOWCERTSubjectPublicKeyInfo *subjectPublicKeyInfo;
SECItem certKey; /* database key for this cert */
SECItem validity;
certDBEntryCert *dbEntry; /* database entry struct */
SECItem subjectKeyID; /* x509v3 subject key identifier */
char *nickname;
char *emailAddr;
NSSLOWCERTCertTrust *trust;
/* the reference count is modified whenever someone looks up, dups
* or destroys a certificate
*/
int referenceCount;
char nicknameSpace[200];
unsigned char certKeySpace[512];
};
#define SEC_CERTIFICATE_VERSION_1 0 /* default created */
#define SEC_CERTIFICATE_VERSION_2 1 /* v2 */
#define SEC_CERTIFICATE_VERSION_3 2 /* v3 extensions */
#define SEC_CRL_VERSION_1 0 /* default */
#define SEC_CRL_VERSION_2 1 /* v2 extensions */
struct NSSLOWCERTIssuerAndSNStr {
SECItem derIssuer;
SECItem serialNumber;
};
typedef SECStatus (* NSSLOWCERTCertCallback)(NSSLOWCERTCertificate *cert, void *arg);
/* This is the typedef for the callback passed to nsslowcert_OpenCertDB() */
/* callback to return database name based on version number */
typedef char * (*NSSLOWCERTDBNameFunc)(void *arg, int dbVersion);
/* XXX Lisa thinks the template declarations belong in cert.h, not here? */
#include "secasn1t.h" /* way down here because I expect template stuff to
* move out of here anyway */
/*
* Certificate Database related definitions and data structures
*/
/* version number of certificate database */
#define CERT_DB_FILE_VERSION 8
#define CERT_DB_V7_FILE_VERSION 7
#define CERT_DB_CONTENT_VERSION 2
#define SEC_DB_ENTRY_HEADER_LEN 3
#define SEC_DB_KEY_HEADER_LEN 1
/* All database entries have this form:
*
* byte offset field
* ----------- -----
* 0 version
* 1 type
* 2 flags
*/
/* database entry types */
typedef enum {
certDBEntryTypeVersion = 0,
certDBEntryTypeCert = 1,
certDBEntryTypeNickname = 2,
certDBEntryTypeSubject = 3,
certDBEntryTypeRevocation = 4,
certDBEntryTypeKeyRevocation = 5,
certDBEntryTypeSMimeProfile = 6,
certDBEntryTypeContentVersion = 7,
certDBEntryTypeBlob = 8
} certDBEntryType;
typedef struct {
certDBEntryType type;
unsigned int version;
unsigned int flags;
PRArenaPool *arena;
} certDBEntryCommon;
/*
* Certificate entry:
*
* byte offset field
* ----------- -----
* 0 sslFlags-msb
* 1 sslFlags-lsb
* 2 emailFlags-msb
* 3 emailFlags-lsb
* 4 objectSigningFlags-msb
* 5 objectSigningFlags-lsb
* 6 derCert-len-msb
* 7 derCert-len-lsb
* 8 nickname-len-msb
* 9 nickname-len-lsb
* ... derCert
* ... nickname
*
* NOTE: the nickname string as stored in the database is null terminated,
* in other words, the last byte of the db entry is always 0
* if a nickname is present.
* NOTE: if nickname is not present, then nickname-len-msb and
* nickname-len-lsb will both be zero.
*/
struct _certDBEntryCert {
certDBEntryCommon common;
certDBEntryCert *next;
NSSLOWCERTCertTrust trust;
SECItem derCert;
char *nickname;
char nicknameSpace[200];
unsigned char derCertSpace[2048];
};
/*
* Certificate Nickname entry:
*
* byte offset field
* ----------- -----
* 0 subjectname-len-msb
* 1 subjectname-len-lsb
* 2... subjectname
*
* The database key for this type of entry is a nickname string
* The "subjectname" value is the DER encoded DN of the identity
* that matches this nickname.
*/
typedef struct {
certDBEntryCommon common;
char *nickname;
SECItem subjectName;
} certDBEntryNickname;
#define DB_NICKNAME_ENTRY_HEADER_LEN 2
/*
* Certificate Subject entry:
*
* byte offset field
* ----------- -----
* 0 ncerts-msb
* 1 ncerts-lsb
* 2 nickname-msb
* 3 nickname-lsb
* 4 emailAddr-msb
* 5 emailAddr-lsb
* ... nickname
* ... emailAddr
* ...+2*i certkey-len-msb
* ...+1+2*i certkey-len-lsb
* ...+2*ncerts+2*i keyid-len-msb
* ...+1+2*ncerts+2*i keyid-len-lsb
* ... certkeys
* ... keyids
*
* The database key for this type of entry is the DER encoded subject name
* The "certkey" value is an array of certificate database lookup keys that
* points to the database entries for the certificates that matche
* this subject.
*
*/
typedef struct _certDBEntrySubject {
certDBEntryCommon common;
SECItem derSubject;
unsigned int ncerts;
char *nickname;
SECItem *certKeys;
SECItem *keyIDs;
char **emailAddrs;
unsigned int nemailAddrs;
} certDBEntrySubject;
#define DB_SUBJECT_ENTRY_HEADER_LEN 6
/*
* Certificate SMIME profile entry:
*
* byte offset field
* ----------- -----
* 0 subjectname-len-msb
* 1 subjectname-len-lsb
* 2 smimeoptions-len-msb
* 3 smimeoptions-len-lsb
* 4 options-date-len-msb
* 5 options-date-len-lsb
* 6... subjectname
* ... smimeoptions
* ... options-date
*
* The database key for this type of entry is the email address string
* The "subjectname" value is the DER encoded DN of the identity
* that matches this nickname.
* The "smimeoptions" value is a string that represents the algorithm
* capabilities on the remote user.
* The "options-date" is the date that the smime options value was created.
* This is generally the signing time of the signed message that contained
* the options. It is a UTCTime value.
*/
typedef struct {
certDBEntryCommon common;
char *emailAddr;
SECItem subjectName;
SECItem smimeOptions;
SECItem optionsDate;
} certDBEntrySMime;
#define DB_SMIME_ENTRY_HEADER_LEN 6
/*
* Crl/krl entry:
*
* byte offset field
* ----------- -----
* 0 derCert-len-msb
* 1 derCert-len-lsb
* 2 url-len-msb
* 3 url-len-lsb
* ... derCert
* ... url
*
* NOTE: the url string as stored in the database is null terminated,
* in other words, the last byte of the db entry is always 0
* if a nickname is present.
* NOTE: if url is not present, then url-len-msb and
* url-len-lsb will both be zero.
*/
#define DB_CRL_ENTRY_HEADER_LEN 4
struct _certDBEntryRevocation {
certDBEntryCommon common;
SECItem derCrl;
char *url; /* where to load the crl from */
};
/*
* Database Version Entry:
*
* byte offset field
* ----------- -----
* only the low level header...
*
* The database key for this type of entry is the string "Version"
*/
typedef struct {
certDBEntryCommon common;
} certDBEntryVersion;
#define SEC_DB_VERSION_KEY "Version"
#define SEC_DB_VERSION_KEY_LEN sizeof(SEC_DB_VERSION_KEY)
/*
* Database Content Version Entry:
*
* byte offset field
* ----------- -----
* 0 contentVersion
*
* The database key for this type of entry is the string "ContentVersion"
*/
typedef struct {
certDBEntryCommon common;
char contentVersion;
} certDBEntryContentVersion;
#define SEC_DB_CONTENT_VERSION_KEY "ContentVersion"
#define SEC_DB_CONTENT_VERSION_KEY_LEN sizeof(SEC_DB_CONTENT_VERSION_KEY)
typedef union {
certDBEntryCommon common;
certDBEntryVersion version;
certDBEntryCert cert;
certDBEntryNickname nickname;
certDBEntrySubject subject;
certDBEntryRevocation revocation;
} certDBEntry;
/* length of the fixed part of a database entry */
#define DBCERT_V4_HEADER_LEN 7
#define DB_CERT_V5_ENTRY_HEADER_LEN 7
#define DB_CERT_V6_ENTRY_HEADER_LEN 7
#define DB_CERT_ENTRY_HEADER_LEN 10
/* common flags for all types of certificates */
#define CERTDB_VALID_PEER (1<<0)
#define CERTDB_TRUSTED (1<<1)
#define CERTDB_SEND_WARN (1<<2)
#define CERTDB_VALID_CA (1<<3)
#define CERTDB_TRUSTED_CA (1<<4) /* trusted for issuing server certs */
#define CERTDB_NS_TRUSTED_CA (1<<5)
#define CERTDB_USER (1<<6)
#define CERTDB_TRUSTED_CLIENT_CA (1<<7) /* trusted for issuing client certs */
#define CERTDB_INVISIBLE_CA (1<<8) /* don't show in UI */
#define CERTDB_GOVT_APPROVED_CA (1<<9) /* can do strong crypto in export ver */
#define CERTDB_NOT_TRUSTED (1<<10) /* explicitly don't trust this cert */
#define CERTDB_TRUSTED_UNKNOWN (1<<11) /* accept trust from another source */
/* bits not affected by the CKO_NETSCAPE_TRUST object */
#define CERTDB_PRESERVE_TRUST_BITS (CERTDB_USER | CERTDB_VALID_PEER | \
CERTDB_NS_TRUSTED_CA | CERTDB_VALID_CA | CERTDB_INVISIBLE_CA | \
CERTDB_GOVT_APPROVED_CA)
#endif /* _PCERTT_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,862 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* The following handles the loading, unloading and management of
* various PCKS #11 modules
*/
/*
* this header file contains routines for parsing PKCS #11 module spec
* strings. It contains 'C' code and should only be included in one module.
* Currently it is included in both softoken and the wrapper.
*/
#include <ctype.h>
#include "pkcs11.h"
#include "seccomon.h"
#include "prprf.h"
#include "secmodt.h"
#include "pk11init.h"
#define SECMOD_ARG_LIBRARY_PARAMETER "library="
#define SECMOD_ARG_NAME_PARAMETER "name="
#define SECMOD_ARG_MODULE_PARAMETER "parameters="
#define SECMOD_ARG_NSS_PARAMETER "NSS="
#define SECMOD_ARG_FORTEZZA_FLAG "FORTEZZA"
#define SECMOD_ARG_ESCAPE '\\'
struct secmodargSlotFlagTable {
char *name;
int len;
unsigned long value;
};
#define SFTK_DEFAULT_CIPHER_ORDER 0
#define SFTK_DEFAULT_TRUST_ORDER 50
#define SECMOD_ARG_ENTRY(arg,flag) \
{ #arg , sizeof(#arg)-1, flag }
static struct secmodargSlotFlagTable secmod_argSlotFlagTable[] = {
SECMOD_ARG_ENTRY(RSA,SECMOD_RSA_FLAG),
SECMOD_ARG_ENTRY(DSA,SECMOD_RSA_FLAG),
SECMOD_ARG_ENTRY(RC2,SECMOD_RC4_FLAG),
SECMOD_ARG_ENTRY(RC4,SECMOD_RC2_FLAG),
SECMOD_ARG_ENTRY(DES,SECMOD_DES_FLAG),
SECMOD_ARG_ENTRY(DH,SECMOD_DH_FLAG),
SECMOD_ARG_ENTRY(FORTEZZA,SECMOD_FORTEZZA_FLAG),
SECMOD_ARG_ENTRY(RC5,SECMOD_RC5_FLAG),
SECMOD_ARG_ENTRY(SHA1,SECMOD_SHA1_FLAG),
SECMOD_ARG_ENTRY(MD5,SECMOD_MD5_FLAG),
SECMOD_ARG_ENTRY(MD2,SECMOD_MD2_FLAG),
SECMOD_ARG_ENTRY(SSL,SECMOD_SSL_FLAG),
SECMOD_ARG_ENTRY(TLS,SECMOD_TLS_FLAG),
SECMOD_ARG_ENTRY(AES,SECMOD_AES_FLAG),
SECMOD_ARG_ENTRY(PublicCerts,SECMOD_FRIENDLY_FLAG),
SECMOD_ARG_ENTRY(RANDOM,SECMOD_RANDOM_FLAG),
};
#define SECMOD_HANDLE_STRING_ARG(param,target,value,command) \
if (PORT_Strncasecmp(param,value,sizeof(value)-1) == 0) { \
param += sizeof(value)-1; \
target = secmod_argFetchValue(param,&next); \
param += next; \
command ;\
} else
#define SECMOD_HANDLE_FINAL_ARG(param) \
{ param = secmod_argSkipParameter(param); } param = secmod_argStrip(param);
static int secmod_argSlotFlagTableSize =
sizeof(secmod_argSlotFlagTable)/sizeof(secmod_argSlotFlagTable[0]);
static PRBool secmod_argGetPair(char c) {
switch (c) {
case '\'': return c;
case '\"': return c;
case '<': return '>';
case '{': return '}';
case '[': return ']';
case '(': return ')';
default: break;
}
return ' ';
}
static PRBool secmod_argIsBlank(char c) {
return isspace(c);
}
static PRBool secmod_argIsEscape(char c) {
return c == '\\';
}
static PRBool secmod_argIsQuote(char c) {
switch (c) {
case '\'':
case '\"':
case '<':
case '{': /* } end curly to keep vi bracket matching working */
case '(': /* ) */
case '[': /* ] */ return PR_TRUE;
default: break;
}
return PR_FALSE;
}
static PRBool secmod_argHasChar(char *v, char c)
{
for ( ;*v; v++) {
if (*v == c) return PR_TRUE;
}
return PR_FALSE;
}
static PRBool secmod_argHasBlanks(char *v)
{
for ( ;*v; v++) {
if (secmod_argIsBlank(*v)) return PR_TRUE;
}
return PR_FALSE;
}
static char *secmod_argStrip(char *c) {
while (*c && secmod_argIsBlank(*c)) c++;
return c;
}
static char *
secmod_argFindEnd(char *string) {
char endChar = ' ';
PRBool lastEscape = PR_FALSE;
if (secmod_argIsQuote(*string)) {
endChar = secmod_argGetPair(*string);
string++;
}
for (;*string; string++) {
if (lastEscape) {
lastEscape = PR_FALSE;
continue;
}
if (secmod_argIsEscape(*string) && !lastEscape) {
lastEscape = PR_TRUE;
continue;
}
if ((endChar == ' ') && secmod_argIsBlank(*string)) break;
if (*string == endChar) {
break;
}
}
return string;
}
static char *
secmod_argFetchValue(char *string, int *pcount)
{
char *end = secmod_argFindEnd(string);
char *retString, *copyString;
PRBool lastEscape = PR_FALSE;
*pcount = (end - string)+1;
if (*pcount == 0) return NULL;
copyString = retString = (char *)PORT_Alloc(*pcount);
if (retString == NULL) return NULL;
if (secmod_argIsQuote(*string)) string++;
for (; string < end; string++) {
if (secmod_argIsEscape(*string) && !lastEscape) {
lastEscape = PR_TRUE;
continue;
}
lastEscape = PR_FALSE;
*copyString++ = *string;
}
*copyString = 0;
return retString;
}
static char *
secmod_argSkipParameter(char *string)
{
char *end;
/* look for the end of the <name>= */
for (;*string; string++) {
if (*string == '=') { string++; break; }
if (secmod_argIsBlank(*string)) return(string);
}
end = secmod_argFindEnd(string);
if (*end) end++;
return end;
}
static SECStatus
secmod_argParseModuleSpec(char *modulespec, char **lib, char **mod,
char **parameters, char **nss)
{
int next;
modulespec = secmod_argStrip(modulespec);
*lib = *mod = *parameters = *nss = 0;
while (*modulespec) {
SECMOD_HANDLE_STRING_ARG(modulespec,*lib,SECMOD_ARG_LIBRARY_PARAMETER,;)
SECMOD_HANDLE_STRING_ARG(modulespec,*mod,SECMOD_ARG_NAME_PARAMETER,;)
SECMOD_HANDLE_STRING_ARG(modulespec,*parameters,
SECMOD_ARG_MODULE_PARAMETER,;)
SECMOD_HANDLE_STRING_ARG(modulespec,*nss,SECMOD_ARG_NSS_PARAMETER,;)
SECMOD_HANDLE_FINAL_ARG(modulespec)
}
return SECSuccess;
}
static char *
secmod_argGetParamValue(char *paramName,char *parameters)
{
char searchValue[256];
int paramLen = strlen(paramName);
char *returnValue = NULL;
int next;
if ((parameters == NULL) || (*parameters == 0)) return NULL;
PORT_Assert(paramLen+2 < sizeof(searchValue));
PORT_Strcpy(searchValue,paramName);
PORT_Strcat(searchValue,"=");
while (*parameters) {
if (PORT_Strncasecmp(parameters,searchValue,paramLen+1) == 0) {
parameters += paramLen+1;
returnValue = secmod_argFetchValue(parameters,&next);
break;
} else {
parameters = secmod_argSkipParameter(parameters);
}
parameters = secmod_argStrip(parameters);
}
return returnValue;
}
static char *
secmod_argNextFlag(char *flags)
{
for (; *flags ; flags++) {
if (*flags == ',') {
flags++;
break;
}
}
return flags;
}
static PRBool
secmod_argHasFlag(char *label, char *flag, char *parameters)
{
char *flags,*index;
int len = strlen(flag);
PRBool found = PR_FALSE;
flags = secmod_argGetParamValue(label,parameters);
if (flags == NULL) return PR_FALSE;
for (index=flags; *index; index=secmod_argNextFlag(index)) {
if (PORT_Strncasecmp(index,flag,len) == 0) {
found=PR_TRUE;
break;
}
}
PORT_Free(flags);
return found;
}
static void
secmod_argSetNewCipherFlags(unsigned long *newCiphers,char *cipherList)
{
newCiphers[0] = newCiphers[1] = 0;
if ((cipherList == NULL) || (*cipherList == 0)) return;
for (;*cipherList; cipherList=secmod_argNextFlag(cipherList)) {
if (PORT_Strncasecmp(cipherList,SECMOD_ARG_FORTEZZA_FLAG,
sizeof(SECMOD_ARG_FORTEZZA_FLAG)-1) == 0) {
newCiphers[0] |= SECMOD_FORTEZZA_FLAG;
}
/* add additional flags here as necessary */
/* direct bit mapping escape */
if (*cipherList == 0) {
if (cipherList[1] == 'l') {
newCiphers[1] |= atoi(&cipherList[2]);
} else {
newCiphers[0] |= atoi(&cipherList[2]);
}
}
}
}
/*
* decode a number. handle octal (leading '0'), hex (leading '0x') or decimal
*/
static long
secmod_argDecodeNumber(char *num)
{
int radix = 10;
unsigned long value = 0;
long retValue = 0;
int sign = 1;
int digit;
if (num == NULL) return retValue;
num = secmod_argStrip(num);
if (*num == '-') {
sign = -1;
num++;
}
if (*num == '0') {
radix = 8;
num++;
if ((*num == 'x') || (*num == 'X')) {
radix = 16;
num++;
}
}
for ( ;*num; num++ ) {
if (isdigit(*num)) {
digit = *num - '0';
} else if ((*num >= 'a') && (*num <= 'f')) {
digit = *num - 'a' + 10;
} else if ((*num >= 'A') && (*num <= 'F')) {
digit = *num - 'A' + 10;
} else {
break;
}
if (digit >= radix) break;
value = value*radix + digit;
}
retValue = ((int) value) * sign;
return retValue;
}
static long
secmod_argReadLong(char *label,char *params, long defValue, PRBool *isdefault)
{
char *value;
long retValue;
if (isdefault) *isdefault = PR_FALSE;
value = secmod_argGetParamValue(label,params);
if (value == NULL) {
if (isdefault) *isdefault = PR_TRUE;
return defValue;
}
retValue = secmod_argDecodeNumber(value);
if (value) PORT_Free(value);
return retValue;
}
static unsigned long
secmod_argSlotFlags(char *label,char *params)
{
char *flags,*index;
unsigned long retValue = 0;
int i;
PRBool all = PR_FALSE;
flags = secmod_argGetParamValue(label,params);
if (flags == NULL) return 0;
if (PORT_Strcasecmp(flags,"all") == 0) all = PR_TRUE;
for (index=flags; *index; index=secmod_argNextFlag(index)) {
for (i=0; i < secmod_argSlotFlagTableSize; i++) {
if (all || (PORT_Strncasecmp(index, secmod_argSlotFlagTable[i].name,
secmod_argSlotFlagTable[i].len) == 0)) {
retValue |= secmod_argSlotFlagTable[i].value;
}
}
}
PORT_Free(flags);
return retValue;
}
static void
secmod_argDecodeSingleSlotInfo(char *name, char *params,
PK11PreSlotInfo *slotInfo)
{
char *askpw;
slotInfo->slotID=secmod_argDecodeNumber(name);
slotInfo->defaultFlags=secmod_argSlotFlags("slotFlags",params);
slotInfo->timeout=secmod_argReadLong("timeout",params, 0, NULL);
askpw = secmod_argGetParamValue("askpw",params);
slotInfo->askpw = 0;
if (askpw) {
if (PORT_Strcasecmp(askpw,"every") == 0) {
slotInfo->askpw = -1;
} else if (PORT_Strcasecmp(askpw,"timeout") == 0) {
slotInfo->askpw = 1;
}
PORT_Free(askpw);
slotInfo->defaultFlags |= PK11_OWN_PW_DEFAULTS;
}
slotInfo->hasRootCerts = secmod_argHasFlag("rootFlags", "hasRootCerts",
params);
slotInfo->hasRootTrust = secmod_argHasFlag("rootFlags", "hasRootTrust",
params);
}
static char *
secmod_argGetName(char *inString, int *next)
{
char *name=NULL;
char *string;
int len;
/* look for the end of the <name>= */
for (string = inString;*string; string++) {
if (*string == '=') { break; }
if (secmod_argIsBlank(*string)) break;
}
len = string - inString;
*next = len;
if (*string == '=') (*next) += 1;
if (len > 0) {
name = PORT_Alloc(len+1);
PORT_Strncpy(name,inString,len);
name[len] = 0;
}
return name;
}
static PK11PreSlotInfo *
secmod_argParseSlotInfo(PRArenaPool *arena, char *slotParams, int *retCount)
{
char *slotIndex;
PK11PreSlotInfo *slotInfo = NULL;
int i=0,count = 0,next;
*retCount = 0;
if ((slotParams == NULL) || (*slotParams == 0)) return NULL;
/* first count the number of slots */
for (slotIndex = secmod_argStrip(slotParams); *slotIndex;
slotIndex = secmod_argStrip(secmod_argSkipParameter(slotIndex))) {
count++;
}
/* get the data structures */
if (arena) {
slotInfo = (PK11PreSlotInfo *)
PORT_ArenaAlloc(arena,count*sizeof(PK11PreSlotInfo));
PORT_Memset(slotInfo,0,count*sizeof(PK11PreSlotInfo));
} else {
slotInfo = (PK11PreSlotInfo *)
PORT_ZAlloc(count*sizeof(PK11PreSlotInfo));
}
if (slotInfo == NULL) return NULL;
for (slotIndex = secmod_argStrip(slotParams), i = 0;
*slotIndex && i < count ; ) {
char *name;
name = secmod_argGetName(slotIndex,&next);
slotIndex += next;
if (!secmod_argIsBlank(*slotIndex)) {
char *args = secmod_argFetchValue(slotIndex,&next);
slotIndex += next;
if (args) {
secmod_argDecodeSingleSlotInfo(name,args,&slotInfo[i]);
i++;
PORT_Free(args);
}
}
if (name) PORT_Free(name);
slotIndex = secmod_argStrip(slotIndex);
}
*retCount = i;
return slotInfo;
}
static char *secmod_nullString = "";
static char *
secmod_formatValue(PRArenaPool *arena, char *value, char quote)
{
char *vp,*vp2,*retval;
int size = 0, escapes = 0;
for (vp=value; *vp ;vp++) {
if ((*vp == quote) || (*vp == SECMOD_ARG_ESCAPE)) escapes++;
size++;
}
if (arena) {
retval = PORT_ArenaZAlloc(arena,size+escapes+1);
} else {
retval = PORT_ZAlloc(size+escapes+1);
}
if (retval == NULL) return NULL;
vp2 = retval;
for (vp=value; *vp; vp++) {
if ((*vp == quote) || (*vp == SECMOD_ARG_ESCAPE))
*vp2++ = SECMOD_ARG_ESCAPE;
*vp2++ = *vp;
}
return retval;
}
static char *secmod_formatPair(char *name,char *value, char quote)
{
char openQuote = quote;
char closeQuote = secmod_argGetPair(quote);
char *newValue = NULL;
char *returnValue;
PRBool need_quote = PR_FALSE;
if (!value || (*value == 0)) return secmod_nullString;
if (secmod_argHasBlanks(value) || secmod_argIsQuote(value[0]))
need_quote=PR_TRUE;
if ((need_quote && secmod_argHasChar(value,closeQuote))
|| secmod_argHasChar(value,SECMOD_ARG_ESCAPE)) {
value = newValue = secmod_formatValue(NULL, value,quote);
if (newValue == NULL) return secmod_nullString;
}
if (need_quote) {
returnValue = PR_smprintf("%s=%c%s%c",name,openQuote,value,closeQuote);
} else {
returnValue = PR_smprintf("%s=%s",name,value);
}
if (returnValue == NULL) returnValue = secmod_nullString;
if (newValue) PORT_Free(newValue);
return returnValue;
}
static char *secmod_formatIntPair(char *name, unsigned long value,
unsigned long def)
{
char *returnValue;
if (value == def) return secmod_nullString;
returnValue = PR_smprintf("%s=%d",name,value);
return returnValue;
}
static void
secmod_freePair(char *pair)
{
if (pair && pair != secmod_nullString) {
PR_smprintf_free(pair);
}
}
#define MAX_FLAG_SIZE sizeof("internal")+sizeof("FIPS")+sizeof("moduleDB")+\
sizeof("moduleDBOnly")+sizeof("critical")
static char *
secmod_mkNSSFlags(PRBool internal, PRBool isFIPS,
PRBool isModuleDB, PRBool isModuleDBOnly, PRBool isCritical)
{
char *flags = (char *)PORT_ZAlloc(MAX_FLAG_SIZE);
PRBool first = PR_TRUE;
PORT_Memset(flags,0,MAX_FLAG_SIZE);
if (internal) {
PORT_Strcat(flags,"internal");
first = PR_FALSE;
}
if (isFIPS) {
if (!first) PORT_Strcat(flags,",");
PORT_Strcat(flags,"FIPS");
first = PR_FALSE;
}
if (isModuleDB) {
if (!first) PORT_Strcat(flags,",");
PORT_Strcat(flags,"moduleDB");
first = PR_FALSE;
}
if (isModuleDBOnly) {
if (!first) PORT_Strcat(flags,",");
PORT_Strcat(flags,"moduleDBOnly");
first = PR_FALSE;
}
if (isCritical) {
if (!first) PORT_Strcat(flags,",");
PORT_Strcat(flags,"critical");
first = PR_FALSE;
}
return flags;
}
static char *
secmod_mkCipherFlags(unsigned long ssl0, unsigned long ssl1)
{
char *cipher = NULL;
int i;
for (i=0; i < sizeof(ssl0)*8; i++) {
if (ssl0 & (1<<i)) {
char *string;
if ((1<<i) == SECMOD_FORTEZZA_FLAG) {
string = PR_smprintf("%s","FORTEZZA");
} else {
string = PR_smprintf("0h0x%08x",1<<i);
}
if (cipher) {
char *tmp;
tmp = PR_smprintf("%s,%s",cipher,string);
PR_smprintf_free(cipher);
PR_smprintf_free(string);
cipher = tmp;
} else {
cipher = string;
}
}
}
for (i=0; i < sizeof(ssl0)*8; i++) {
if (ssl1 & (1<<i)) {
if (cipher) {
char *tmp;
tmp = PR_smprintf("%s,0l0x%08x",cipher,1<<i);
PR_smprintf_free(cipher);
cipher = tmp;
} else {
cipher = PR_smprintf("0l0x%08x",1<<i);
}
}
}
return cipher;
}
static char *
secmod_mkSlotFlags(unsigned long defaultFlags)
{
char *flags=NULL;
int i,j;
for (i=0; i < sizeof(defaultFlags)*8; i++) {
if (defaultFlags & (1<<i)) {
char *string = NULL;
for (j=0; j < secmod_argSlotFlagTableSize; j++) {
if (secmod_argSlotFlagTable[j].value == ( 1UL << i )) {
string = secmod_argSlotFlagTable[j].name;
break;
}
}
if (string) {
if (flags) {
char *tmp;
tmp = PR_smprintf("%s,%s",flags,string);
PR_smprintf_free(flags);
flags = tmp;
} else {
flags = PR_smprintf("%s",string);
}
}
}
}
return flags;
}
#define SECMOD_MAX_ROOT_FLAG_SIZE sizeof("hasRootCerts")+sizeof("hasRootTrust")
static char *
secmod_mkRootFlags(PRBool hasRootCerts, PRBool hasRootTrust)
{
char *flags= (char *)PORT_ZAlloc(SECMOD_MAX_ROOT_FLAG_SIZE);
PRBool first = PR_TRUE;
PORT_Memset(flags,0,SECMOD_MAX_ROOT_FLAG_SIZE);
if (hasRootCerts) {
PORT_Strcat(flags,"hasRootCerts");
first = PR_FALSE;
}
if (hasRootTrust) {
if (!first) PORT_Strcat(flags,",");
PORT_Strcat(flags,"hasRootTrust");
first = PR_FALSE;
}
return flags;
}
static char *
secmod_mkSlotString(unsigned long slotID, unsigned long defaultFlags,
unsigned long timeout, unsigned char askpw_in,
PRBool hasRootCerts, PRBool hasRootTrust) {
char *askpw,*flags,*rootFlags,*slotString;
char *flagPair,*rootFlagsPair;
switch (askpw_in) {
case 0xff:
askpw = "every";
break;
case 1:
askpw = "timeout";
break;
default:
askpw = "any";
break;
}
flags = secmod_mkSlotFlags(defaultFlags);
rootFlags = secmod_mkRootFlags(hasRootCerts,hasRootTrust);
flagPair=secmod_formatPair("slotFlags",flags,'\'');
rootFlagsPair=secmod_formatPair("rootFlags",rootFlags,'\'');
if (flags) PR_smprintf_free(flags);
if (rootFlags) PORT_Free(rootFlags);
if (defaultFlags & PK11_OWN_PW_DEFAULTS) {
slotString = PR_smprintf("0x%08lx=[%s askpw=%s timeout=%d %s]",
(PRUint32)slotID,flagPair,askpw,timeout,
rootFlagsPair);
} else {
slotString = PR_smprintf("0x%08lx=[%s %s]",
(PRUint32)slotID,flagPair,rootFlagsPair);
}
secmod_freePair(flagPair);
secmod_freePair(rootFlagsPair);
return slotString;
}
static char *
secmod_mkNSS(char **slotStrings, int slotCount, PRBool internal, PRBool isFIPS,
PRBool isModuleDB, PRBool isModuleDBOnly, PRBool isCritical,
unsigned long trustOrder, unsigned long cipherOrder,
unsigned long ssl0, unsigned long ssl1) {
int slotLen, i;
char *slotParams, *ciphers, *nss, *nssFlags, *tmp;
char *trustOrderPair,*cipherOrderPair,*slotPair,*cipherPair,*flagPair;
/* now let's build up the string
* first the slot infos
*/
slotLen=0;
for (i=0; i < (int)slotCount; i++) {
slotLen += PORT_Strlen(slotStrings[i])+1;
}
slotLen += 1; /* space for the final NULL */
slotParams = (char *)PORT_ZAlloc(slotLen);
PORT_Memset(slotParams,0,slotLen);
for (i=0; i < (int)slotCount; i++) {
PORT_Strcat(slotParams,slotStrings[i]);
PORT_Strcat(slotParams," ");
PR_smprintf_free(slotStrings[i]);
slotStrings[i]=NULL;
}
/*
* now the NSS structure
*/
nssFlags = secmod_mkNSSFlags(internal,isFIPS,isModuleDB,isModuleDBOnly,
isCritical);
/* for now only the internal module is critical */
ciphers = secmod_mkCipherFlags(ssl0, ssl1);
trustOrderPair=secmod_formatIntPair("trustOrder",trustOrder,
SFTK_DEFAULT_TRUST_ORDER);
cipherOrderPair=secmod_formatIntPair("cipherOrder",cipherOrder,
SFTK_DEFAULT_CIPHER_ORDER);
slotPair=secmod_formatPair("slotParams",slotParams,'{'); /* } */
if (slotParams) PORT_Free(slotParams);
cipherPair=secmod_formatPair("ciphers",ciphers,'\'');
if (ciphers) PR_smprintf_free(ciphers);
flagPair=secmod_formatPair("Flags",nssFlags,'\'');
if (nssFlags) PORT_Free(nssFlags);
nss = PR_smprintf("%s %s %s %s %s",trustOrderPair,
cipherOrderPair,slotPair,cipherPair,flagPair);
secmod_freePair(trustOrderPair);
secmod_freePair(cipherOrderPair);
secmod_freePair(slotPair);
secmod_freePair(cipherPair);
secmod_freePair(flagPair);
tmp = secmod_argStrip(nss);
if (*tmp == '\0') {
PR_smprintf_free(nss);
nss = NULL;
}
return nss;
}
static char *
secmod_mkNewModuleSpec(char *dllName, char *commonName, char *parameters,
char *NSS) {
char *moduleSpec;
char *lib,*name,*param,*nss;
/*
* now the final spec
*/
lib = secmod_formatPair("library",dllName,'\"');
name = secmod_formatPair("name",commonName,'\"');
param = secmod_formatPair("parameters",parameters,'\"');
nss = secmod_formatPair("NSS",NSS,'\"');
moduleSpec = PR_smprintf("%s %s %s %s", lib,name,param,nss);
secmod_freePair(lib);
secmod_freePair(name);
secmod_freePair(param);
secmod_freePair(nss);
return (moduleSpec);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,323 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* RSA Labs
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document
* is granted provided that it is identified as "RSA Security In.c Public-Key
* Cryptography Standards (PKCS)" in all material mentioning or referencing
* this document.
*
* The latest version of this header can be found at:
* http://www.rsalabs.com/pkcs/pkcs-11/index.html
*/
#ifndef _PKCS11_H_
#define _PKCS11_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/* Before including this file (pkcs11.h) (or pkcs11t.h by
* itself), 6 platform-specific macros must be defined. These
* macros are described below, and typical definitions for them
* are also given. Be advised that these definitions can depend
* on both the platform and the compiler used (and possibly also
* on whether a PKCS #11 library is linked statically or
* dynamically).
*
* In addition to defining these 6 macros, the packing convention
* for PKCS #11 structures should be set. The PKCS #11
* convention on packing is that structures should be 1-byte
* aligned.
*
* In a Win32 environment, this might be done by using the
* following preprocessor directive before including pkcs11.h
* or pkcs11t.h:
*
* #pragma pack(push, cryptoki, 1)
*
* and using the following preprocessor directive after including
* pkcs11.h or pkcs11t.h:
*
* #pragma pack(pop, cryptoki)
*
* In a Win16 environment, this might be done by using the
* following preprocessor directive before including pkcs11.h
* or pkcs11t.h:
*
* #pragma pack(1)
*
* In a UNIX environment, you're on your own here. You might
* not need to do anything.
*
*
* Now for the macros:
*
*
* 1. CK_PTR: The indirection string for making a pointer to an
* object. It can be used like this:
*
* typedef CK_BYTE CK_PTR CK_BYTE_PTR;
*
* In a Win32 environment, it might be defined by
*
* #define CK_PTR *
*
* In a Win16 environment, it might be defined by
*
* #define CK_PTR far *
*
* In a UNIX environment, it might be defined by
*
* #define CK_PTR *
*
*
* 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
* an exportable PKCS #11 library function definition out of a
* return type and a function name. It should be used in the
* following fashion to define the exposed PKCS #11 functions in
* a PKCS #11 library:
*
* CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
* CK_VOID_PTR pReserved
* )
* {
* ...
* }
*
* For defining a function in a Win32 PKCS #11 .dll, it might be
* defined by
*
* #define CK_DEFINE_FUNCTION(returnType, name) \
* returnType __declspec(dllexport) name
*
* For defining a function in a Win16 PKCS #11 .dll, it might be
* defined by
*
* #define CK_DEFINE_FUNCTION(returnType, name) \
* returnType __export _far _pascal name
*
* In a UNIX environment, it might be defined by
*
* #define CK_DEFINE_FUNCTION(returnType, name) \
* returnType name
*
*
* 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
* an importable PKCS #11 library function declaration out of a
* return type and a function name. It should be used in the
* following fashion:
*
* extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
* CK_VOID_PTR pReserved
* );
*
* For declaring a function in a Win32 PKCS #11 .dll, it might
* be defined by
*
* #define CK_DECLARE_FUNCTION(returnType, name) \
* returnType __declspec(dllimport) name
*
* For declaring a function in a Win16 PKCS #11 .dll, it might
* be defined by
*
* #define CK_DECLARE_FUNCTION(returnType, name) \
* returnType __export _far _pascal name
*
* In a UNIX environment, it might be defined by
*
* #define CK_DECLARE_FUNCTION(returnType, name) \
* returnType name
*
*
* 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
* which makes a PKCS #11 API function pointer declaration or
* function pointer type declaration out of a return type and a
* function name. It should be used in the following fashion:
*
* // Define funcPtr to be a pointer to a PKCS #11 API function
* // taking arguments args and returning CK_RV.
* CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
*
* or
*
* // Define funcPtrType to be the type of a pointer to a
* // PKCS #11 API function taking arguments args and returning
* // CK_RV, and then define funcPtr to be a variable of type
* // funcPtrType.
* typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
* funcPtrType funcPtr;
*
* For accessing functions in a Win32 PKCS #11 .dll, in might be
* defined by
*
* #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
* returnType __declspec(dllimport) (* name)
*
* For accessing functions in a Win16 PKCS #11 .dll, it might be
* defined by
*
* #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
* returnType __export _far _pascal (* name)
*
* In a UNIX environment, it might be defined by
*
* #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
* returnType (* name)
*
*
* 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
* a function pointer type for an application callback out of
* a return type for the callback and a name for the callback.
* It should be used in the following fashion:
*
* CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
*
* to declare a function pointer, myCallback, to a callback
* which takes arguments args and returns a CK_RV. It can also
* be used like this:
*
* typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
* myCallbackType myCallback;
*
* In a Win32 environment, it might be defined by
*
* #define CK_CALLBACK_FUNCTION(returnType, name) \
* returnType (* name)
*
* In a Win16 environment, it might be defined by
*
* #define CK_CALLBACK_FUNCTION(returnType, name) \
* returnType _far _pascal (* name)
*
* In a UNIX environment, it might be defined by
*
* #define CK_CALLBACK_FUNCTION(returnType, name) \
* returnType (* name)
*
*
* 6. NULL_PTR: This macro is the value of a NULL pointer.
*
* In any ANSI/ISO C environment (and in many others as well),
* this should be defined by
*
* #ifndef NULL_PTR
* #define NULL_PTR 0
* #endif
*/
/* All the various PKCS #11 types and #define'd values are in the
* file pkcs11t.h. */
#include "pkcs11t.h"
#define __PASTE(x,y) x##y
/* packing defines */
#include "pkcs11p.h"
/* ==============================================================
* Define the "extern" form of all the entry points.
* ==============================================================
*/
#define CK_NEED_ARG_LIST 1
#define CK_PKCS11_FUNCTION_INFO(name) \
CK_DECLARE_FUNCTION(CK_RV, name)
/* pkcs11f.h has all the information about the PKCS #11
* function prototypes. */
#include "pkcs11f.h"
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
/* ==============================================================
* Define the typedef form of all the entry points. That is, for
* each PKCS #11 function C_XXX, define a type CK_C_XXX which is
* a pointer to that kind of function.
* ==============================================================
*/
#define CK_NEED_ARG_LIST 1
#define CK_PKCS11_FUNCTION_INFO(name) \
typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
/* pkcs11f.h has all the information about the PKCS #11
* function prototypes. */
#include "pkcs11f.h"
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
/* ==============================================================
* Define structed vector of entry points. A CK_FUNCTION_LIST
* contains a CK_VERSION indicating a library's PKCS #11 version
* and then a whole slew of function pointers to the routines in
* the library. This type was declared, but not defined, in
* pkcs11t.h.
* ==============================================================
*/
#define CK_PKCS11_FUNCTION_INFO(name) \
__PASTE(CK_,name) name;
struct CK_FUNCTION_LIST {
CK_VERSION version; /* PKCS #11 version */
/* Pile all the function pointers into the CK_FUNCTION_LIST. */
/* pkcs11f.h has all the information about the PKCS #11
* function prototypes. */
#include "pkcs11f.h"
};
#undef CK_PKCS11_FUNCTION_INFO
#undef __PASTE
/* unpack */
#include "pkcs11u.h"
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,937 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document
* is granted provided that it is identified as "RSA Security In.c Public-Key
* Cryptography Standards (PKCS)" in all material mentioning or referencing
* this document.
*/
/* This function contains pretty much everything about all the */
/* PKCS #11 function prototypes. Because this information is */
/* used for more than just declaring function prototypes, the */
/* order of the functions appearing herein is important, and */
/* should not be altered. */
/* General-purpose */
/* C_Initialize initializes the PKCS #11 library. */
CK_PKCS11_FUNCTION_INFO(C_Initialize)
#ifdef CK_NEED_ARG_LIST
(
CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
* cast to CK_C_INITIALIZE_ARGS_PTR
* and dereferenced */
);
#endif
/* C_Finalize indicates that an application is done with the
* PKCS #11 library. */
CK_PKCS11_FUNCTION_INFO(C_Finalize)
#ifdef CK_NEED_ARG_LIST
(
CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
);
#endif
/* C_GetInfo returns general information about PKCS #11. */
CK_PKCS11_FUNCTION_INFO(C_GetInfo)
#ifdef CK_NEED_ARG_LIST
(
CK_INFO_PTR pInfo /* location that receives information */
);
#endif
/* C_GetFunctionList returns the function list. */
CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
#ifdef CK_NEED_ARG_LIST
(
CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
* function list */
);
#endif
/* Slot and token management */
/* C_GetSlotList obtains a list of slots in the system. */
CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
#ifdef CK_NEED_ARG_LIST
(
CK_BBOOL tokenPresent, /* only slots with tokens? */
CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
CK_ULONG_PTR pulCount /* receives number of slots */
);
#endif
/* C_GetSlotInfo obtains information about a particular slot in
* the system. */
CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
#ifdef CK_NEED_ARG_LIST
(
CK_SLOT_ID slotID, /* the ID of the slot */
CK_SLOT_INFO_PTR pInfo /* receives the slot information */
);
#endif
/* C_GetTokenInfo obtains information about a particular token
* in the system. */
CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
#ifdef CK_NEED_ARG_LIST
(
CK_SLOT_ID slotID, /* ID of the token's slot */
CK_TOKEN_INFO_PTR pInfo /* receives the token information */
);
#endif
/* C_GetMechanismList obtains a list of mechanism types
* supported by a token. */
CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
#ifdef CK_NEED_ARG_LIST
(
CK_SLOT_ID slotID, /* ID of token's slot */
CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
CK_ULONG_PTR pulCount /* gets # of mechs. */
);
#endif
/* C_GetMechanismInfo obtains information about a particular
* mechanism possibly supported by a token. */
CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
#ifdef CK_NEED_ARG_LIST
(
CK_SLOT_ID slotID, /* ID of the token's slot */
CK_MECHANISM_TYPE type, /* type of mechanism */
CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
);
#endif
/* C_InitToken initializes a token. */
CK_PKCS11_FUNCTION_INFO(C_InitToken)
#ifdef CK_NEED_ARG_LIST
(
/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
CK_SLOT_ID slotID, /* ID of the token's slot */
CK_CHAR_PTR pPin, /* the SO's initial PIN */
CK_ULONG ulPinLen, /* length in bytes of the PIN */
CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
);
#endif
/* C_InitPIN initializes the normal user's PIN. */
CK_PKCS11_FUNCTION_INFO(C_InitPIN)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_CHAR_PTR pPin, /* the normal user's PIN */
CK_ULONG ulPinLen /* length in bytes of the PIN */
);
#endif
/* C_SetPIN modifies the PIN of the user who is logged in. */
CK_PKCS11_FUNCTION_INFO(C_SetPIN)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_CHAR_PTR pOldPin, /* the old PIN */
CK_ULONG ulOldLen, /* length of the old PIN */
CK_CHAR_PTR pNewPin, /* the new PIN */
CK_ULONG ulNewLen /* length of the new PIN */
);
#endif
/* Session management */
/* C_OpenSession opens a session between an application and a
* token. */
CK_PKCS11_FUNCTION_INFO(C_OpenSession)
#ifdef CK_NEED_ARG_LIST
(
CK_SLOT_ID slotID, /* the slot's ID */
CK_FLAGS flags, /* from CK_SESSION_INFO */
CK_VOID_PTR pApplication, /* passed to callback */
CK_NOTIFY Notify, /* callback function */
CK_SESSION_HANDLE_PTR phSession /* gets session handle */
);
#endif
/* C_CloseSession closes a session between an application and a
* token. */
CK_PKCS11_FUNCTION_INFO(C_CloseSession)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession /* the session's handle */
);
#endif
/* C_CloseAllSessions closes all sessions with a token. */
CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
#ifdef CK_NEED_ARG_LIST
(
CK_SLOT_ID slotID /* the token's slot */
);
#endif
/* C_GetSessionInfo obtains information about the session. */
CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_SESSION_INFO_PTR pInfo /* receives session info */
);
#endif
/* C_GetOperationState obtains the state of the cryptographic operation
* in a session. */
CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pOperationState, /* gets state */
CK_ULONG_PTR pulOperationStateLen /* gets state length */
);
#endif
/* C_SetOperationState restores the state of the cryptographic
* operation in a session. */
CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pOperationState, /* holds state */
CK_ULONG ulOperationStateLen, /* holds state length */
CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
);
#endif
/* C_Login logs a user into a token. */
CK_PKCS11_FUNCTION_INFO(C_Login)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_USER_TYPE userType, /* the user type */
CK_CHAR_PTR pPin, /* the user's PIN */
CK_ULONG ulPinLen /* the length of the PIN */
);
#endif
/* C_Logout logs a user out from a token. */
CK_PKCS11_FUNCTION_INFO(C_Logout)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession /* the session's handle */
);
#endif
/* Object management */
/* C_CreateObject creates a new object. */
CK_PKCS11_FUNCTION_INFO(C_CreateObject)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
CK_ULONG ulCount, /* attributes in template */
CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
);
#endif
/* C_CopyObject copies an object, creating a new object for the
* copy. */
CK_PKCS11_FUNCTION_INFO(C_CopyObject)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_OBJECT_HANDLE hObject, /* the object's handle */
CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
CK_ULONG ulCount, /* attributes in template */
CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
);
#endif
/* C_DestroyObject destroys an object. */
CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_OBJECT_HANDLE hObject /* the object's handle */
);
#endif
/* C_GetObjectSize gets the size of an object in bytes. */
CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_OBJECT_HANDLE hObject, /* the object's handle */
CK_ULONG_PTR pulSize /* receives size of object */
);
#endif
/* C_GetAttributeValue obtains the value of one or more object
* attributes. */
CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_OBJECT_HANDLE hObject, /* the object's handle */
CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
CK_ULONG ulCount /* attributes in template */
);
#endif
/* C_SetAttributeValue modifies the value of one or more object
* attributes */
CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_OBJECT_HANDLE hObject, /* the object's handle */
CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
CK_ULONG ulCount /* attributes in template */
);
#endif
/* C_FindObjectsInit initializes a search for token and session
* objects that match a template. */
CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
CK_ULONG ulCount /* attrs in search template */
);
#endif
/* C_FindObjects continues a search for token and session
* objects that match a template, obtaining additional object
* handles. */
CK_PKCS11_FUNCTION_INFO(C_FindObjects)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
CK_ULONG ulMaxObjectCount, /* max handles to get */
CK_ULONG_PTR pulObjectCount /* actual # returned */
);
#endif
/* C_FindObjectsFinal finishes a search for token and session
* objects. */
CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession /* the session's handle */
);
#endif
/* Encryption and decryption */
/* C_EncryptInit initializes an encryption operation. */
CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
CK_OBJECT_HANDLE hKey /* handle of encryption key */
);
#endif
/* C_Encrypt encrypts single-part data. */
CK_PKCS11_FUNCTION_INFO(C_Encrypt)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pData, /* the plaintext data */
CK_ULONG ulDataLen, /* bytes of plaintext */
CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
);
#endif
/* C_EncryptUpdate continues a multiple-part encryption
* operation. */
CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pPart, /* the plaintext data */
CK_ULONG ulPartLen, /* plaintext data len */
CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
);
#endif
/* C_EncryptFinal finishes a multiple-part encryption
* operation. */
CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session handle */
CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
);
#endif
/* C_DecryptInit initializes a decryption operation. */
CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
CK_OBJECT_HANDLE hKey /* handle of decryption key */
);
#endif
/* C_Decrypt decrypts encrypted data in a single part. */
CK_PKCS11_FUNCTION_INFO(C_Decrypt)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pEncryptedData, /* ciphertext */
CK_ULONG ulEncryptedDataLen, /* ciphertext length */
CK_BYTE_PTR pData, /* gets plaintext */
CK_ULONG_PTR pulDataLen /* gets p-text size */
);
#endif
/* C_DecryptUpdate continues a multiple-part decryption
* operation. */
CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pEncryptedPart, /* encrypted data */
CK_ULONG ulEncryptedPartLen, /* input length */
CK_BYTE_PTR pPart, /* gets plaintext */
CK_ULONG_PTR pulPartLen /* p-text size */
);
#endif
/* C_DecryptFinal finishes a multiple-part decryption
* operation. */
CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pLastPart, /* gets plaintext */
CK_ULONG_PTR pulLastPartLen /* p-text size */
);
#endif
/* Message digesting */
/* C_DigestInit initializes a message-digesting operation. */
CK_PKCS11_FUNCTION_INFO(C_DigestInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
);
#endif
/* C_Digest digests data in a single part. */
CK_PKCS11_FUNCTION_INFO(C_Digest)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pData, /* data to be digested */
CK_ULONG ulDataLen, /* bytes of data to digest */
CK_BYTE_PTR pDigest, /* gets the message digest */
CK_ULONG_PTR pulDigestLen /* gets digest length */
);
#endif
/* C_DigestUpdate continues a multiple-part message-digesting
* operation. */
CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pPart, /* data to be digested */
CK_ULONG ulPartLen /* bytes of data to be digested */
);
#endif
/* C_DigestKey continues a multi-part message-digesting
* operation, by digesting the value of a secret key as part of
* the data already digested. */
CK_PKCS11_FUNCTION_INFO(C_DigestKey)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_OBJECT_HANDLE hKey /* secret key to digest */
);
#endif
/* C_DigestFinal finishes a multiple-part message-digesting
* operation. */
CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pDigest, /* gets the message digest */
CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
);
#endif
/* Signing and MACing */
/* C_SignInit initializes a signature (private key encryption)
* operation, where the signature is (will be) an appendix to
* the data, and plaintext cannot be recovered from the
*signature. */
CK_PKCS11_FUNCTION_INFO(C_SignInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
CK_OBJECT_HANDLE hKey /* handle of signature key */
);
#endif
/* C_Sign signs (encrypts with private key) data in a single
* part, where the signature is (will be) an appendix to the
* data, and plaintext cannot be recovered from the signature. */
CK_PKCS11_FUNCTION_INFO(C_Sign)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pData, /* the data to sign */
CK_ULONG ulDataLen, /* count of bytes to sign */
CK_BYTE_PTR pSignature, /* gets the signature */
CK_ULONG_PTR pulSignatureLen /* gets signature length */
);
#endif
/* C_SignUpdate continues a multiple-part signature operation,
* where the signature is (will be) an appendix to the data,
* and plaintext cannot be recovered from the signature. */
CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pPart, /* the data to sign */
CK_ULONG ulPartLen /* count of bytes to sign */
);
#endif
/* C_SignFinal finishes a multiple-part signature operation,
* returning the signature. */
CK_PKCS11_FUNCTION_INFO(C_SignFinal)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pSignature, /* gets the signature */
CK_ULONG_PTR pulSignatureLen /* gets signature length */
);
#endif
/* C_SignRecoverInit initializes a signature operation, where
* the data can be recovered from the signature. */
CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
CK_OBJECT_HANDLE hKey /* handle of the signature key */
);
#endif
/* C_SignRecover signs data in a single operation, where the
* data can be recovered from the signature. */
CK_PKCS11_FUNCTION_INFO(C_SignRecover)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pData, /* the data to sign */
CK_ULONG ulDataLen, /* count of bytes to sign */
CK_BYTE_PTR pSignature, /* gets the signature */
CK_ULONG_PTR pulSignatureLen /* gets signature length */
);
#endif
/* Verifying signatures and MACs */
/* C_VerifyInit initializes a verification operation, where the
* signature is an appendix to the data, and plaintext cannot
* cannot be recovered from the signature (e.g. DSA). */
CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
CK_OBJECT_HANDLE hKey /* verification key */
);
#endif
/* C_Verify verifies a signature in a single-part operation,
* where the signature is an appendix to the data, and plaintext
* cannot be recovered from the signature. */
CK_PKCS11_FUNCTION_INFO(C_Verify)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pData, /* signed data */
CK_ULONG ulDataLen, /* length of signed data */
CK_BYTE_PTR pSignature, /* signature */
CK_ULONG ulSignatureLen /* signature length*/
);
#endif
/* C_VerifyUpdate continues a multiple-part verification
* operation, where the signature is an appendix to the data,
* and plaintext cannot be recovered from the signature. */
CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pPart, /* signed data */
CK_ULONG ulPartLen /* length of signed data */
);
#endif
/* C_VerifyFinal finishes a multiple-part verification
* operation, checking the signature. */
CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pSignature, /* signature to verify */
CK_ULONG ulSignatureLen /* signature length */
);
#endif
/* C_VerifyRecoverInit initializes a signature verification
* operation, where the data is recovered from the signature. */
CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
CK_OBJECT_HANDLE hKey /* verification key */
);
#endif
/* C_VerifyRecover verifies a signature in a single-part
* operation, where the data is recovered from the signature. */
CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pSignature, /* signature to verify */
CK_ULONG ulSignatureLen, /* signature length */
CK_BYTE_PTR pData, /* gets signed data */
CK_ULONG_PTR pulDataLen /* gets signed data len */
);
#endif
/* Dual-function cryptographic operations */
/* C_DigestEncryptUpdate continues a multiple-part digesting
* and encryption operation. */
CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pPart, /* the plaintext data */
CK_ULONG ulPartLen, /* plaintext length */
CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
);
#endif
/* C_DecryptDigestUpdate continues a multiple-part decryption and
* digesting operation. */
CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pEncryptedPart, /* ciphertext */
CK_ULONG ulEncryptedPartLen, /* ciphertext length */
CK_BYTE_PTR pPart, /* gets plaintext */
CK_ULONG_PTR pulPartLen /* gets plaintext len */
);
#endif
/* C_SignEncryptUpdate continues a multiple-part signing and
* encryption operation. */
CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pPart, /* the plaintext data */
CK_ULONG ulPartLen, /* plaintext length */
CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
);
#endif
/* C_DecryptVerifyUpdate continues a multiple-part decryption and
* verify operation. */
CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_BYTE_PTR pEncryptedPart, /* ciphertext */
CK_ULONG ulEncryptedPartLen, /* ciphertext length */
CK_BYTE_PTR pPart, /* gets plaintext */
CK_ULONG_PTR pulPartLen /* gets p-text length */
);
#endif
/* Key management */
/* C_GenerateKey generates a secret key, creating a new key
* object. */
CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* key generation mech. */
CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
CK_ULONG ulCount, /* # of attrs in template */
CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
);
#endif
/* C_GenerateKeyPair generates a public-key/private-key pair,
* creating new key objects. */
CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session
* handle */
CK_MECHANISM_PTR pMechanism, /* key-gen
* mech. */
CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template
* for pub.
* key */
CK_ULONG ulPublicKeyAttributeCount, /* # pub.
* attrs. */
CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template
* for priv.
* key */
CK_ULONG ulPrivateKeyAttributeCount, /* # priv.
* attrs. */
CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub.
* key
* handle */
CK_OBJECT_HANDLE_PTR phPrivateKey /* gets
* priv. key
* handle */
);
#endif
/* C_WrapKey wraps (i.e., encrypts) a key. */
CK_PKCS11_FUNCTION_INFO(C_WrapKey)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
CK_OBJECT_HANDLE hKey, /* key to be wrapped */
CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
);
#endif
/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
* key object. */
CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
CK_BYTE_PTR pWrappedKey, /* the wrapped key */
CK_ULONG ulWrappedKeyLen, /* wrapped key len */
CK_ATTRIBUTE_PTR pTemplate, /* new key template */
CK_ULONG ulAttributeCount, /* template length */
CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
);
#endif
/* C_DeriveKey derives a key from a base key, creating a new key
* object. */
CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* session's handle */
CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
CK_OBJECT_HANDLE hBaseKey, /* base key */
CK_ATTRIBUTE_PTR pTemplate, /* new key template */
CK_ULONG ulAttributeCount, /* template length */
CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
);
#endif
/* Random number generation */
/* C_SeedRandom mixes additional seed material into the token's
* random number generator. */
CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pSeed, /* the seed material */
CK_ULONG ulSeedLen /* length of seed material */
);
#endif
/* C_GenerateRandom generates random data. */
CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR RandomData, /* receives the random data */
CK_ULONG ulRandomLen /* # of bytes to generate */
);
#endif
/* Parallel function management */
/* C_GetFunctionStatus is a legacy function; it obtains an
* updated status of a function running in parallel with an
* application. */
CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession /* the session's handle */
);
#endif
/* C_CancelFunction is a legacy function; it cancels a function
* running in parallel. */
CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
#ifdef CK_NEED_ARG_LIST
(
CK_SESSION_HANDLE hSession /* the session's handle */
);
#endif
/* Functions added in for PKCS #11 Version 2.01 or later */
/* C_WaitForSlotEvent waits for a slot event (token insertion,
* removal, etc.) to occur. */
CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
#ifdef CK_NEED_ARG_LIST
(
CK_FLAGS flags, /* blocking/nonblocking flag */
CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
);
#endif

View File

@@ -1,697 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* Internal data structures and functions used by pkcs11.c
*/
#ifndef _PKCS11I_H_
#define _PKCS11I_H_ 1
#include "nssilock.h"
#include "seccomon.h"
#include "secoidt.h"
#include "lowkeyti.h"
#include "pkcs11t.h"
#include "pcertt.h"
/*
* Configuration Defines
*
* The following defines affect the space verse speed trade offs of
* the PKCS #11 module. For the most part the current settings are optimized
* for web servers, where we want faster speed and lower lock contention at
* the expense of space.
*/
/*
* The attribute allocation strategy is static allocation:
* Attributes are pre-allocated as part of the session object and used from
* the object array.
*/
#define MAX_OBJS_ATTRS 45 /* number of attributes to preallocate in
* the object (must me the absolute max) */
#define ATTR_SPACE 50 /* Maximum size of attribute data before extra
* data needs to be allocated. This is set to
* enough space to hold an SSL MASTER secret */
#define NSC_STRICT PR_FALSE /* forces the code to do strict template
* matching when doing C_FindObject on token
* objects. This will slow down search in
* NSS. */
/* default search block allocations and increments */
#define NSC_CERT_BLOCK_SIZE 50
#define NSC_SEARCH_BLOCK_SIZE 5
#define NSC_SLOT_LIST_BLOCK_SIZE 10
#define NSC_FIPS_MODULE 1
#define NSC_NON_FIPS_MODULE 0
/* these are data base storage hashes, not cryptographic hashes.. The define
* the effective size of the various object hash tables */
/* clients care more about memory usage than lookup performance on
* cyrptographic objects. Clients also have less objects around to play with
*
* we eventually should make this configurable at runtime! Especially now that
* NSS is a shared library.
*/
#define SPACE_ATTRIBUTE_HASH_SIZE 32
#define SPACE_TOKEN_OBJECT_HASH_SIZE 32
#define SPACE_SESSION_HASH_SIZE 32
#define TIME_ATTRIBUTE_HASH_SIZE 32
#define TIME_TOKEN_OBJECT_HASH_SIZE 1024
#define TIME_SESSION_HASH_SIZE 1024
#define MAX_OBJECT_LIST_SIZE 800
/* how many objects to keep on the free list
* before we start freeing them */
#define MAX_KEY_LEN 256
#define MULTIACCESS "multiaccess:"
/*
* LOG2_BUCKETS_PER_SESSION_LOCK must be a prime number.
* With SESSION_HASH_SIZE=1024, LOG2 can be 9, 5, 1, or 0.
* With SESSION_HASH_SIZE=4096, LOG2 can be 11, 9, 5, 1, or 0.
*
* HASH_SIZE LOG2_BUCKETS_PER BUCKETS_PER_LOCK NUMBER_OF_BUCKETS
* 1024 9 512 2
* 1024 5 32 32
* 1024 1 2 512
* 1024 0 1 1024
* 4096 11 2048 2
* 4096 9 512 8
* 4096 5 32 128
* 4096 1 2 2048
* 4096 0 1 4096
*/
#define LOG2_BUCKETS_PER_SESSION_LOCK 1
#define BUCKETS_PER_SESSION_LOCK (1 << (LOG2_BUCKETS_PER_SESSION_LOCK))
/* NOSPREAD sessionID to hash table index macro has been slower. */
/* define typedefs, double as forward declarations as well */
typedef struct SFTKAttributeStr SFTKAttribute;
typedef struct SFTKObjectListStr SFTKObjectList;
typedef struct SFTKObjectFreeListStr SFTKObjectFreeList;
typedef struct SFTKObjectListElementStr SFTKObjectListElement;
typedef struct SFTKObjectStr SFTKObject;
typedef struct SFTKSessionObjectStr SFTKSessionObject;
typedef struct SFTKTokenObjectStr SFTKTokenObject;
typedef struct SFTKSessionStr SFTKSession;
typedef struct SFTKSlotStr SFTKSlot;
typedef struct SFTKSessionContextStr SFTKSessionContext;
typedef struct SFTKSearchResultsStr SFTKSearchResults;
typedef struct SFTKHashVerifyInfoStr SFTKHashVerifyInfo;
typedef struct SFTKHashSignInfoStr SFTKHashSignInfo;
typedef struct SFTKSSLMACInfoStr SFTKSSLMACInfo;
/* define function pointer typdefs for pointer tables */
typedef void (*SFTKDestroy)(void *, PRBool);
typedef void (*SFTKBegin)(void *);
typedef SECStatus (*SFTKCipher)(void *,void *,unsigned int *,unsigned int,
void *, unsigned int);
typedef SECStatus (*SFTKVerify)(void *,void *,unsigned int,void *,unsigned int);
typedef void (*SFTKHash)(void *,void *,unsigned int);
typedef void (*SFTKEnd)(void *,void *,unsigned int *,unsigned int);
typedef void (*SFTKFree)(void *);
/* Value to tell if an attribute is modifiable or not.
* NEVER: attribute is only set on creation.
* ONCOPY: attribute is set on creation and can only be changed on copy.
* SENSITIVE: attribute can only be changed to TRUE.
* ALWAYS: attribute can always be changed.
*/
typedef enum {
SFTK_NEVER = 0,
SFTK_ONCOPY = 1,
SFTK_SENSITIVE = 2,
SFTK_ALWAYS = 3
} SFTKModifyType;
/*
* Free Status Enum... tell us more information when we think we're
* deleting an object.
*/
typedef enum {
SFTK_DestroyFailure,
SFTK_Destroyed,
SFTK_Busy
} SFTKFreeStatus;
/*
* attribute values of an object.
*/
struct SFTKAttributeStr {
SFTKAttribute *next;
SFTKAttribute *prev;
PRBool freeAttr;
PRBool freeData;
/*must be called handle to make sftkqueue_find work */
CK_ATTRIBUTE_TYPE handle;
CK_ATTRIBUTE attrib;
unsigned char space[ATTR_SPACE];
};
/*
* doubly link list of objects
*/
struct SFTKObjectListStr {
SFTKObjectList *next;
SFTKObjectList *prev;
SFTKObject *parent;
};
struct SFTKObjectFreeListStr {
SFTKObject *head;
PZLock *lock;
int count;
};
/*
* PKCS 11 crypto object structure
*/
struct SFTKObjectStr {
SFTKObject *next;
SFTKObject *prev;
CK_OBJECT_CLASS objclass;
CK_OBJECT_HANDLE handle;
int refCount;
PZLock *refLock;
SFTKSlot *slot;
void *objectInfo;
SFTKFree infoFree;
};
struct SFTKTokenObjectStr {
SFTKObject obj;
SECItem dbKey;
};
struct SFTKSessionObjectStr {
SFTKObject obj;
SFTKObjectList sessionList;
PZLock *attributeLock;
SFTKSession *session;
PRBool wasDerived;
int nextAttr;
SFTKAttribute attrList[MAX_OBJS_ATTRS];
PRBool optimizeSpace;
unsigned int hashSize;
SFTKAttribute *head[1];
};
/*
* struct to deal with a temparary list of objects
*/
struct SFTKObjectListElementStr {
SFTKObjectListElement *next;
SFTKObject *object;
};
/*
* Area to hold Search results
*/
struct SFTKSearchResultsStr {
CK_OBJECT_HANDLE *handles;
int size;
int index;
int array_size;
};
/*
* the universal crypto/hash/sign/verify context structure
*/
typedef enum {
SFTK_ENCRYPT,
SFTK_DECRYPT,
SFTK_HASH,
SFTK_SIGN,
SFTK_SIGN_RECOVER,
SFTK_VERIFY,
SFTK_VERIFY_RECOVER
} SFTKContextType;
#define SFTK_MAX_BLOCK_SIZE 16
/* currently SHA512 is the biggest hash length */
#define SFTK_MAX_MAC_LENGTH 64
#define SFTK_INVALID_MAC_SIZE 0xffffffff
struct SFTKSessionContextStr {
SFTKContextType type;
PRBool multi; /* is multipart */
PRBool doPad; /* use PKCS padding for block ciphers */
unsigned int blockSize; /* blocksize for padding */
unsigned int padDataLength; /* length of the valid data in padbuf */
unsigned char padBuf[SFTK_MAX_BLOCK_SIZE];
unsigned char macBuf[SFTK_MAX_BLOCK_SIZE];
CK_ULONG macSize; /* size of a general block cipher mac*/
void *cipherInfo;
void *hashInfo;
unsigned int cipherInfoLen;
CK_MECHANISM_TYPE currentMech;
SFTKCipher update;
SFTKHash hashUpdate;
SFTKEnd end;
SFTKDestroy destroy;
SFTKDestroy hashdestroy;
SFTKVerify verify;
unsigned int maxLen;
SFTKObject *key;
};
/*
* Sessions (have objects)
*/
struct SFTKSessionStr {
SFTKSession *next;
SFTKSession *prev;
CK_SESSION_HANDLE handle;
int refCount;
PZLock *objectLock;
int objectIDCount;
CK_SESSION_INFO info;
CK_NOTIFY notify;
CK_VOID_PTR appData;
SFTKSlot *slot;
SFTKSearchResults *search;
SFTKSessionContext *enc_context;
SFTKSessionContext *hash_context;
SFTKSessionContext *sign_context;
SFTKObjectList *objects[1];
};
/*
* slots (have sessions and objects)
*
* The array of sessionLock's protect the session hash table (head[])
* as well as the reference count of session objects in that bucket
* (head[]->refCount), objectLock protects all elements of the token
* object hash table (tokObjects[], tokenIDCount, and tokenHashTable),
* and slotLock protects the remaining protected elements:
* password, isLoggedIn, ssoLoggedIn, and sessionCount
*/
struct SFTKSlotStr {
CK_SLOT_ID slotID;
PZLock *slotLock;
PZLock **sessionLock;
unsigned int numSessionLocks;
unsigned long sessionLockMask;
PZLock *objectLock;
SECItem *password;
PRBool hasTokens;
PRBool isLoggedIn;
PRBool ssoLoggedIn;
PRBool needLogin;
PRBool DB_loaded;
PRBool readOnly;
PRBool optimizeSpace;
NSSLOWCERTCertDBHandle *certDB;
NSSLOWKEYDBHandle *keyDB;
int minimumPinLen;
PRInt32 sessionIDCount; /* atomically incremented */
int sessionIDConflict; /* not protected by a lock */
int sessionCount;
PRInt32 rwSessionCount; /* set by atomic operations */
int tokenIDCount;
int index;
PLHashTable *tokenHashTable;
SFTKObject **tokObjects;
unsigned int tokObjHashSize;
SFTKSession **head;
unsigned int sessHashSize;
char tokDescription[33];
char slotDescription[64];
};
/*
* special joint operations Contexts
*/
struct SFTKHashVerifyInfoStr {
SECOidTag hashOid;
NSSLOWKEYPublicKey *key;
};
struct SFTKHashSignInfoStr {
SECOidTag hashOid;
NSSLOWKEYPrivateKey *key;
};
/* context for the Final SSLMAC message */
struct SFTKSSLMACInfoStr {
void *hashContext;
SFTKBegin begin;
SFTKHash update;
SFTKEnd end;
CK_ULONG macSize;
int padSize;
unsigned char key[MAX_KEY_LEN];
unsigned int keySize;
};
/*
* session handle modifiers
*/
#define SFTK_SESSION_SLOT_MASK 0xff000000L
/*
* object handle modifiers
*/
#define SFTK_TOKEN_MASK 0x80000000L
#define SFTK_TOKEN_MAGIC 0x80000000L
#define SFTK_TOKEN_TYPE_MASK 0x70000000L
/* keydb (high bit == 0) */
#define SFTK_TOKEN_TYPE_PRIV 0x10000000L
#define SFTK_TOKEN_TYPE_PUB 0x20000000L
#define SFTK_TOKEN_TYPE_KEY 0x30000000L
/* certdb (high bit == 1) */
#define SFTK_TOKEN_TYPE_TRUST 0x40000000L
#define SFTK_TOKEN_TYPE_CRL 0x50000000L
#define SFTK_TOKEN_TYPE_SMIME 0x60000000L
#define SFTK_TOKEN_TYPE_CERT 0x70000000L
#define SFTK_TOKEN_KRL_HANDLE (SFTK_TOKEN_MAGIC|SFTK_TOKEN_TYPE_CRL|1)
/* how big a password/pin we can deal with */
#define SFTK_MAX_PIN 255
/* slot ID's */
#define NETSCAPE_SLOT_ID 1
#define PRIVATE_KEY_SLOT_ID 2
#define FIPS_SLOT_ID 3
/* slot helper macros */
#define sftk_SlotFromSession(sp) ((sp)->slot)
#define sftk_isToken(id) (((id) & SFTK_TOKEN_MASK) == SFTK_TOKEN_MAGIC)
/* the session hash multiplier (see bug 201081) */
#define SHMULTIPLIER 1791398085
/* queueing helper macros */
#define sftk_hash(value,size) \
((PRUint32)((value) * SHMULTIPLIER) & (size-1))
#define sftkqueue_add(element,id,head,hash_size) \
{ int tmp = sftk_hash(id,hash_size); \
(element)->next = (head)[tmp]; \
(element)->prev = NULL; \
if ((head)[tmp]) (head)[tmp]->prev = (element); \
(head)[tmp] = (element); }
#define sftkqueue_find(element,id,head,hash_size) \
for( (element) = (head)[sftk_hash(id,hash_size)]; (element) != NULL; \
(element) = (element)->next) { \
if ((element)->handle == (id)) { break; } }
#define sftkqueue_is_queued(element,id,head,hash_size) \
( ((element)->next) || ((element)->prev) || \
((head)[sftk_hash(id,hash_size)] == (element)) )
#define sftkqueue_delete(element,id,head,hash_size) \
if ((element)->next) (element)->next->prev = (element)->prev; \
if ((element)->prev) (element)->prev->next = (element)->next; \
else (head)[sftk_hash(id,hash_size)] = ((element)->next); \
(element)->next = NULL; \
(element)->prev = NULL; \
#define sftkqueue_init_element(element) \
(element)->prev = NULL;
#define sftkqueue_add2(element, id, index, head) \
{ \
(element)->next = (head)[index]; \
if ((head)[index]) \
(head)[index]->prev = (element); \
(head)[index] = (element); \
}
#define sftkqueue_find2(element, id, index, head) \
for ( (element) = (head)[index]; \
(element) != NULL; \
(element) = (element)->next) { \
if ((element)->handle == (id)) { break; } \
}
#define sftkqueue_delete2(element, id, index, head) \
if ((element)->next) (element)->next->prev = (element)->prev; \
if ((element)->prev) (element)->prev->next = (element)->next; \
else (head)[index] = ((element)->next);
#define sftkqueue_clear_deleted_element(element) \
(element)->next = NULL; \
(element)->prev = NULL; \
/* sessionID (handle) is used to determine session lock bucket */
#ifdef NOSPREAD
/* NOSPREAD: (ID>>L2LPB) & (perbucket-1) */
#define SFTK_SESSION_LOCK(slot,handle) \
((slot)->sessionLock[((handle) >> LOG2_BUCKETS_PER_SESSION_LOCK) \
& (slot)->sessionLockMask])
#else
/* SPREAD: ID & (perbucket-1) */
#define SFTK_SESSION_LOCK(slot,handle) \
((slot)->sessionLock[(handle) & (slot)->sessionLockMask])
#endif
/* expand an attribute & secitem structures out */
#define sftk_attr_expand(ap) (ap)->type,(ap)->pValue,(ap)->ulValueLen
#define sftk_item_expand(ip) (ip)->data,(ip)->len
typedef struct sftk_token_parametersStr {
CK_SLOT_ID slotID;
char *configdir;
char *certPrefix;
char *keyPrefix;
char *tokdes;
char *slotdes;
int minPW;
PRBool readOnly;
PRBool noCertDB;
PRBool noKeyDB;
PRBool forceOpen;
PRBool pwRequired;
PRBool optimizeSpace;
} sftk_token_parameters;
typedef struct sftk_parametersStr {
char *configdir;
char *secmodName;
char *man;
char *libdes;
PRBool readOnly;
PRBool noModDB;
PRBool noCertDB;
PRBool forceOpen;
PRBool pwRequired;
PRBool optimizeSpace;
sftk_token_parameters *tokens;
int token_count;
} sftk_parameters;
/* machine dependent path stuff used by dbinit.c and pk11db.c */
#ifdef macintosh
#define PATH_SEPARATOR ":"
#define SECMOD_DB "Security Modules"
#define CERT_DB_FMT "%sCertificates%s"
#define KEY_DB_FMT "%sKey Database%s"
#else
#define PATH_SEPARATOR "/"
#define SECMOD_DB "secmod.db"
#define CERT_DB_FMT "%scert%s.db"
#define KEY_DB_FMT "%skey%s.db"
#endif
SEC_BEGIN_PROTOS
extern int nsf_init;
extern CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS);
extern CK_RV nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS);
extern CK_RV nsc_CommonGetSlotList(CK_BBOOL tokPresent,
CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount, int moduleIndex);
/* shared functions between PKCS11.c and SFTKFIPS.c */
extern CK_RV SFTK_SlotInit(char *configdir,sftk_token_parameters *params,
int moduleIndex);
/* internal utility functions used by pkcs11.c */
extern SFTKAttribute *sftk_FindAttribute(SFTKObject *object,
CK_ATTRIBUTE_TYPE type);
extern void sftk_FreeAttribute(SFTKAttribute *attribute);
extern CK_RV sftk_AddAttributeType(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
void *valPtr,
CK_ULONG length);
extern CK_RV sftk_Attribute2SecItem(PLArenaPool *arena, SECItem *item,
SFTKObject *object, CK_ATTRIBUTE_TYPE type);
extern unsigned int sftk_GetLengthInBits(unsigned char *buf,
unsigned int bufLen);
extern CK_RV sftk_ConstrainAttribute(SFTKObject *object,
CK_ATTRIBUTE_TYPE type, int minLength, int maxLength, int minMultiple);
extern PRBool sftk_hasAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type);
extern PRBool sftk_isTrue(SFTKObject *object, CK_ATTRIBUTE_TYPE type);
extern void sftk_DeleteAttributeType(SFTKObject *object,
CK_ATTRIBUTE_TYPE type);
extern CK_RV sftk_Attribute2SecItem(PLArenaPool *arena, SECItem *item,
SFTKObject *object, CK_ATTRIBUTE_TYPE type);
extern CK_RV sftk_Attribute2SSecItem(PLArenaPool *arena, SECItem *item,
SFTKObject *object,
CK_ATTRIBUTE_TYPE type);
extern SFTKModifyType sftk_modifyType(CK_ATTRIBUTE_TYPE type,
CK_OBJECT_CLASS inClass);
extern PRBool sftk_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass);
extern char *sftk_getString(SFTKObject *object, CK_ATTRIBUTE_TYPE type);
extern void sftk_nullAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type);
extern CK_RV sftk_GetULongAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
CK_ULONG *longData);
extern CK_RV sftk_forceAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
void *value, unsigned int len);
extern CK_RV sftk_defaultAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
void *value, unsigned int len);
extern unsigned int sftk_MapTrust(CK_TRUST trust, PRBool clientAuth);
extern SFTKObject *sftk_NewObject(SFTKSlot *slot);
extern CK_RV sftk_CopyObject(SFTKObject *destObject, SFTKObject *srcObject);
extern SFTKFreeStatus sftk_FreeObject(SFTKObject *object);
extern CK_RV sftk_DeleteObject(SFTKSession *session, SFTKObject *object);
extern void sftk_ReferenceObject(SFTKObject *object);
extern SFTKObject *sftk_ObjectFromHandle(CK_OBJECT_HANDLE handle,
SFTKSession *session);
extern void sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object);
extern void sftk_AddObject(SFTKSession *session, SFTKObject *object);
extern CK_RV sftk_searchObjectList(SFTKSearchResults *search,
SFTKObject **head, unsigned int size,
PZLock *lock, CK_ATTRIBUTE_PTR inTemplate,
int count, PRBool isLoggedIn);
extern SFTKObjectListElement *sftk_FreeObjectListElement(
SFTKObjectListElement *objectList);
extern void sftk_FreeObjectList(SFTKObjectListElement *objectList);
extern void sftk_FreeSearch(SFTKSearchResults *search);
extern CK_RV sftk_handleObject(SFTKObject *object, SFTKSession *session);
extern SFTKSlot *sftk_SlotFromID(CK_SLOT_ID slotID);
extern SFTKSlot *sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle);
extern SFTKSession *sftk_SessionFromHandle(CK_SESSION_HANDLE handle);
extern void sftk_FreeSession(SFTKSession *session);
extern SFTKSession *sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify,
CK_VOID_PTR pApplication, CK_FLAGS flags);
extern void sftk_update_state(SFTKSlot *slot,SFTKSession *session);
extern void sftk_update_all_states(SFTKSlot *slot);
extern void sftk_FreeContext(SFTKSessionContext *context);
extern void sftk_InitFreeLists(void);
extern void sftk_CleanupFreeLists(void);
extern NSSLOWKEYPublicKey *sftk_GetPubKey(SFTKObject *object,
CK_KEY_TYPE key_type, CK_RV *crvp);
extern NSSLOWKEYPrivateKey *sftk_GetPrivKey(SFTKObject *object,
CK_KEY_TYPE key_type, CK_RV *crvp);
extern void sftk_FormatDESKey(unsigned char *key, int length);
extern PRBool sftk_CheckDESKey(unsigned char *key);
extern PRBool sftk_IsWeakKey(unsigned char *key,CK_KEY_TYPE key_type);
extern CK_RV secmod_parseParameters(char *param, sftk_parameters *parsed,
PRBool isFIPS);
extern void secmod_freeParams(sftk_parameters *params);
extern char *secmod_getSecmodName(char *params, char **domain,
char **filename, PRBool *rw);
extern char ** secmod_ReadPermDB(const char *domain, const char *filename,
const char *dbname, char *params, PRBool rw);
extern SECStatus secmod_DeletePermDB(const char *domain, const char *filename,
const char *dbname, char *args, PRBool rw);
extern SECStatus secmod_AddPermDB(const char *domain, const char *filename,
const char *dbname, char *module, PRBool rw);
extern SECStatus secmod_ReleasePermDBData(const char *domain,
const char *filename, const char *dbname, char **specList, PRBool rw);
/* mechanism allows this operation */
extern CK_RV sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op);
/*
* OK there are now lots of options here, lets go through them all:
*
* configdir - base directory where all the cert, key, and module datbases live.
* certPrefix - prefix added to the beginning of the cert database example: "
* "https-server1-"
* keyPrefix - prefix added to the beginning of the key database example: "
* "https-server1-"
* secmodName - name of the security module database (usually "secmod.db").
* readOnly - Boolean: true if the databases are to be openned read only.
* nocertdb - Don't open the cert DB and key DB's, just initialize the
* Volatile certdb.
* nomoddb - Don't open the security module DB, just initialize the
* PKCS #11 module.
* forceOpen - Continue to force initializations even if the databases cannot
* be opened.
*/
CK_RV sftk_DBInit(const char *configdir, const char *certPrefix,
const char *keyPrefix, PRBool readOnly, PRBool noCertDB,
PRBool noKeyDB, PRBool forceOpen,
NSSLOWCERTCertDBHandle **certDB, NSSLOWKEYDBHandle **keyDB);
void sftk_DBShutdown(NSSLOWCERTCertDBHandle *certHandle,
NSSLOWKEYDBHandle *keyHandle);
const char *sftk_EvaluateConfigDir(const char *configdir, char **domain);
/*
* narrow objects
*/
SFTKSessionObject * sftk_narrowToSessionObject(SFTKObject *);
SFTKTokenObject * sftk_narrowToTokenObject(SFTKObject *);
/*
* token object utilities
*/
void sftk_addHandle(SFTKSearchResults *search, CK_OBJECT_HANDLE handle);
PRBool sftk_poisonHandle(SFTKSlot *slot, SECItem *dbkey,
CK_OBJECT_HANDLE handle);
PRBool sftk_tokenMatch(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class,
CK_ATTRIBUTE_PTR theTemplate,int count);
CK_OBJECT_HANDLE sftk_mkHandle(SFTKSlot *slot,
SECItem *dbKey, CK_OBJECT_HANDLE class);
SFTKObject * sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey,
CK_OBJECT_HANDLE handle);
SFTKTokenObject *sftk_convertSessionToToken(SFTKObject *so);
/****************************************
* implement TLS Pseudo Random Function (PRF)
*/
extern SECStatus
sftk_PRF(const SECItem *secret, const char *label, SECItem *seed,
SECItem *result, PRBool isFIPS);
extern CK_RV
sftk_TLSPRFInit(SFTKSessionContext *context,
SFTKObject * key,
CK_KEY_TYPE key_type);
SEC_END_PROTOS
#endif /* _PKCS11I_H_ */

View File

@@ -1,236 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dr Stephen Henson <stephen.henson@gemplus.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _PKCS11N_H_
#define _PKCS11N_H_
#ifdef DEBUG
static const char CKT_CVS_ID[] = "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.12 $ $Date: 2005-01-20 02:25:50 $";
#endif /* DEBUG */
/*
* pkcs11n.h
*
* This file contains the NSS-specific type definitions for Cryptoki
* (PKCS#11).
*/
/*
* NSSCK_VENDOR_NETSCAPE
*
* Cryptoki reserves the high half of all the number spaces for
* vendor-defined use. I'd like to keep all of our Netscape-
* specific values together, but not in the oh-so-obvious
* 0x80000001, 0x80000002, etc. area. So I've picked an offset,
* and constructed values for the beginnings of our spaces.
*
* Note that some "historical" Netscape values don't fall within
* this range.
*/
#define NSSCK_VENDOR_NETSCAPE 0x4E534350 /* NSCP */
/*
* Netscape-defined object classes
*
*/
#define CKO_NETSCAPE (CKO_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
#define CKO_NETSCAPE_CRL (CKO_NETSCAPE + 1)
#define CKO_NETSCAPE_SMIME (CKO_NETSCAPE + 2)
#define CKO_NETSCAPE_TRUST (CKO_NETSCAPE + 3)
#define CKO_NETSCAPE_BUILTIN_ROOT_LIST (CKO_NETSCAPE + 4)
/*
* Netscape-defined key types
*
*/
#define CKK_NETSCAPE (CKK_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
#define CKK_NETSCAPE_PKCS8 (CKK_NETSCAPE + 1)
/*
* Netscape-defined certificate types
*
*/
#define CKC_NETSCAPE (CKC_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
/*
* Netscape-defined object attributes
*
*/
#define CKA_NETSCAPE (CKA_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
#define CKA_NETSCAPE_URL (CKA_NETSCAPE + 1)
#define CKA_NETSCAPE_EMAIL (CKA_NETSCAPE + 2)
#define CKA_NETSCAPE_SMIME_INFO (CKA_NETSCAPE + 3)
#define CKA_NETSCAPE_SMIME_TIMESTAMP (CKA_NETSCAPE + 4)
#define CKA_NETSCAPE_PKCS8_SALT (CKA_NETSCAPE + 5)
#define CKA_NETSCAPE_PASSWORD_CHECK (CKA_NETSCAPE + 6)
#define CKA_NETSCAPE_EXPIRES (CKA_NETSCAPE + 7)
#define CKA_NETSCAPE_KRL (CKA_NETSCAPE + 8)
#define CKA_NETSCAPE_PQG_COUNTER (CKA_NETSCAPE + 20)
#define CKA_NETSCAPE_PQG_SEED (CKA_NETSCAPE + 21)
#define CKA_NETSCAPE_PQG_H (CKA_NETSCAPE + 22)
#define CKA_NETSCAPE_PQG_SEED_BITS (CKA_NETSCAPE + 23)
/*
* Trust attributes:
*
* If trust goes standard, these probably will too. So I'll
* put them all in one place.
*/
#define CKA_TRUST (CKA_NETSCAPE + 0x2000)
/* "Usage" key information */
#define CKA_TRUST_DIGITAL_SIGNATURE (CKA_TRUST + 1)
#define CKA_TRUST_NON_REPUDIATION (CKA_TRUST + 2)
#define CKA_TRUST_KEY_ENCIPHERMENT (CKA_TRUST + 3)
#define CKA_TRUST_DATA_ENCIPHERMENT (CKA_TRUST + 4)
#define CKA_TRUST_KEY_AGREEMENT (CKA_TRUST + 5)
#define CKA_TRUST_KEY_CERT_SIGN (CKA_TRUST + 6)
#define CKA_TRUST_CRL_SIGN (CKA_TRUST + 7)
/* "Purpose" trust information */
#define CKA_TRUST_SERVER_AUTH (CKA_TRUST + 8)
#define CKA_TRUST_CLIENT_AUTH (CKA_TRUST + 9)
#define CKA_TRUST_CODE_SIGNING (CKA_TRUST + 10)
#define CKA_TRUST_EMAIL_PROTECTION (CKA_TRUST + 11)
#define CKA_TRUST_IPSEC_END_SYSTEM (CKA_TRUST + 12)
#define CKA_TRUST_IPSEC_TUNNEL (CKA_TRUST + 13)
#define CKA_TRUST_IPSEC_USER (CKA_TRUST + 14)
#define CKA_TRUST_TIME_STAMPING (CKA_TRUST + 15)
#define CKA_TRUST_STEP_UP_APPROVED (CKA_TRUST + 16)
#define CKA_CERT_SHA1_HASH (CKA_TRUST + 100)
#define CKA_CERT_MD5_HASH (CKA_TRUST + 101)
/* Netscape trust stuff */
/* XXX fgmr new ones here-- step-up, etc. */
/* HISTORICAL: define used to pass in the database key for DSA private keys */
#define CKA_NETSCAPE_DB 0xD5A0DB00L
#define CKA_NETSCAPE_TRUST 0x80000001L
/*
* Netscape-defined crypto mechanisms
*
*/
#define CKM_NETSCAPE (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
#define CKM_NETSCAPE_AES_KEY_WRAP (CKM_NETSCAPE + 1)
#define CKM_NETSCAPE_AES_KEY_WRAP_PAD (CKM_NETSCAPE + 2)
/*
* HISTORICAL:
* Do not attempt to use these. They are only used by NETSCAPE's internal
* PKCS #11 interface. Most of these are place holders for other mechanism
* and will change in the future.
*/
#define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002L
#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003L
#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004L
#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC 0x80000005L
#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006L
#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007L
#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008L
#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009L
#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aL
#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bL
#define CKM_TLS_PRF_GENERAL 0x80000373L
/*
* Netscape-defined return values
*
*/
#define CKR_NETSCAPE (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
#define CKR_NETSCAPE_CERTDB_FAILED (CKR_NETSCAPE + 1)
#define CKR_NETSCAPE_KEYDB_FAILED (CKR_NETSCAPE + 2)
/*
* Trust info
*
* This isn't part of the Cryptoki standard (yet), so I'm putting
* all the definitions here. Some of this would move to nssckt.h
* if trust info were made part of the standard. In view of this
* possibility, I'm putting my (Netscape) values in the netscape
* vendor space, like everything else.
*/
typedef CK_ULONG CK_TRUST;
/* The following trust types are defined: */
#define CKT_VENDOR_DEFINED 0x80000000
#define CKT_NETSCAPE (CKT_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE)
/* If trust goes standard, these'll probably drop out of vendor space. */
#define CKT_NETSCAPE_TRUSTED (CKT_NETSCAPE + 1)
#define CKT_NETSCAPE_TRUSTED_DELEGATOR (CKT_NETSCAPE + 2)
#define CKT_NETSCAPE_UNTRUSTED (CKT_NETSCAPE + 3)
#define CKT_NETSCAPE_MUST_VERIFY (CKT_NETSCAPE + 4)
#define CKT_NETSCAPE_TRUST_UNKNOWN (CKT_NETSCAPE + 5) /* default */
/*
* These may well remain Netscape-specific; I'm only using them
* to cache resolution data.
*/
#define CKT_NETSCAPE_VALID (CKT_NETSCAPE + 10)
#define CKT_NETSCAPE_VALID_DELEGATOR (CKT_NETSCAPE + 11)
/*
* These are not really PKCS #11 values specifically. They are the 'loadable'
* module spec NSS uses. The are available for others to use as well, but not
* part of the formal PKCS #11 spec.
*
* The function 'FIND' returns an array of PKCS #11 initialization strings
* The function 'ADD' takes a PKCS #11 initialization string and stores it.
* The function 'DEL' takes a 'name= library=' value and deletes the associated
* string.
* The function 'RELEASE' frees the array returned by 'FIND'
*/
#define SECMOD_MODULE_DB_FUNCTION_FIND 0
#define SECMOD_MODULE_DB_FUNCTION_ADD 1
#define SECMOD_MODULE_DB_FUNCTION_DEL 2
#define SECMOD_MODULE_DB_FUNCTION_RELEASE 3
typedef char ** (PR_CALLBACK *SECMODModuleDBFunc)(unsigned long function,
char *parameters, void *moduleSpec);
#endif /* _PKCS11N_H_ */

View File

@@ -1,54 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document
* is granted provided that it is identified as "RSA Security Inc. Public-Key
* Cryptography Standards (PKCS)" in all material mentioning or referencing
* this document.
*/
/* these data types are platform/implementation dependent. */
/*
* Packing was removed from the shipped RSA header files, even
* though it's still needed. put in a central file to help merging..
*/
#if defined(_WIN32)
#ifdef _MSC_VER
#pragma warning(disable:4103)
#endif
#pragma pack(push, cryptoki, 1)
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,52 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document
* is granted provided that it is identified as "RSA Security Inc. Public-Key
* Cryptography Standards (PKCS)" in all material mentioning or referencing
* this document.
*/
/*
* reset any packing set by pkcs11p.h
*/
#if defined (_WIN32)
#ifdef _MSC_VER
#pragma warning(disable:4103)
#endif
#pragma pack(pop, cryptoki)
#endif

View File

@@ -1,138 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nspr.h"
#include "sechash.h"
#include "blapi.h" /* below the line */
static void *
null_hash_new_context(void)
{
return NULL;
}
static void *
null_hash_clone_context(void *v)
{
PORT_Assert(v == NULL);
return NULL;
}
static void
null_hash_begin(void *v)
{
}
static void
null_hash_update(void *v, const unsigned char *input, unsigned int length)
{
}
static void
null_hash_end(void *v, unsigned char *output, unsigned int *outLen,
unsigned int maxOut)
{
*outLen = 0;
}
static void
null_hash_destroy_context(void *v, PRBool b)
{
PORT_Assert(v == NULL);
}
const SECHashObject SECRawHashObjects[] = {
{ 0,
(void * (*)(void)) null_hash_new_context,
(void * (*)(void *)) null_hash_clone_context,
(void (*)(void *, PRBool)) null_hash_destroy_context,
(void (*)(void *)) null_hash_begin,
(void (*)(void *, const unsigned char *, unsigned int)) null_hash_update,
(void (*)(void *, unsigned char *, unsigned int *,
unsigned int)) null_hash_end
},
{ MD2_LENGTH,
(void * (*)(void)) MD2_NewContext,
(void * (*)(void *)) null_hash_clone_context,
(void (*)(void *, PRBool)) MD2_DestroyContext,
(void (*)(void *)) MD2_Begin,
(void (*)(void *, const unsigned char *, unsigned int)) MD2_Update,
(void (*)(void *, unsigned char *, unsigned int *, unsigned int)) MD2_End
},
{ MD5_LENGTH,
(void * (*)(void)) MD5_NewContext,
(void * (*)(void *)) null_hash_clone_context,
(void (*)(void *, PRBool)) MD5_DestroyContext,
(void (*)(void *)) MD5_Begin,
(void (*)(void *, const unsigned char *, unsigned int)) MD5_Update,
(void (*)(void *, unsigned char *, unsigned int *, unsigned int)) MD5_End
},
{ SHA1_LENGTH,
(void * (*)(void)) SHA1_NewContext,
(void * (*)(void *)) null_hash_clone_context,
(void (*)(void *, PRBool)) SHA1_DestroyContext,
(void (*)(void *)) SHA1_Begin,
(void (*)(void *, const unsigned char *, unsigned int)) SHA1_Update,
(void (*)(void *, unsigned char *, unsigned int *, unsigned int)) SHA1_End
},
{ SHA256_LENGTH,
(void * (*)(void)) SHA256_NewContext,
(void * (*)(void *)) null_hash_clone_context,
(void (*)(void *, PRBool)) SHA256_DestroyContext,
(void (*)(void *)) SHA256_Begin,
(void (*)(void *, const unsigned char *, unsigned int)) SHA256_Update,
(void (*)(void *, unsigned char *, unsigned int *, unsigned int)) SHA256_End
},
{ SHA384_LENGTH,
(void * (*)(void)) SHA384_NewContext,
(void * (*)(void *)) null_hash_clone_context,
(void (*)(void *, PRBool)) SHA384_DestroyContext,
(void (*)(void *)) SHA384_Begin,
(void (*)(void *, const unsigned char *, unsigned int)) SHA384_Update,
(void (*)(void *, unsigned char *, unsigned int *, unsigned int)) SHA384_End
},
{ SHA512_LENGTH,
(void * (*)(void)) SHA512_NewContext,
(void * (*)(void *)) null_hash_clone_context,
(void (*)(void *, PRBool)) SHA512_DestroyContext,
(void (*)(void *)) SHA512_Begin,
(void (*)(void *, const unsigned char *, unsigned int)) SHA512_Update,
(void (*)(void *, unsigned char *, unsigned int *, unsigned int)) SHA512_End
},
};

View File

@@ -1,879 +0,0 @@
/*
* PKCS#1 encoding and decoding functions.
* This file is believed to contain no code licensed from other parties.
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: rsawrapr.c,v 1.8 2005-04-04 09:27:42 julien.pierre.bugs%sun.com Exp $ */
#include "blapi.h"
#include "softoken.h"
#include "sechash.h"
#include "lowkeyi.h"
#include "secerr.h"
#define RSA_BLOCK_MIN_PAD_LEN 8
#define RSA_BLOCK_FIRST_OCTET 0x00
#define RSA_BLOCK_PRIVATE0_PAD_OCTET 0x00
#define RSA_BLOCK_PRIVATE_PAD_OCTET 0xff
#define RSA_BLOCK_AFTER_PAD_OCTET 0x00
#define OAEP_SALT_LEN 8
#define OAEP_PAD_LEN 8
#define OAEP_PAD_OCTET 0x00
#define FLAT_BUFSIZE 512 /* bytes to hold flattened SHA1Context. */
static SHA1Context *
SHA1_CloneContext(SHA1Context *original)
{
SHA1Context * clone = NULL;
unsigned char *pBuf;
int sha1ContextSize = SHA1_FlattenSize(original);
SECStatus frv;
unsigned char buf[FLAT_BUFSIZE];
PORT_Assert(sizeof buf >= sha1ContextSize);
if (sizeof buf >= sha1ContextSize) {
pBuf = buf;
} else {
pBuf = PORT_Alloc(sha1ContextSize);
if (!pBuf)
goto done;
}
frv = SHA1_Flatten(original, pBuf);
if (frv == SECSuccess) {
clone = SHA1_Resurrect(pBuf, NULL);
memset(pBuf, 0, sha1ContextSize);
}
done:
if (pBuf != buf)
PORT_Free(pBuf);
return clone;
}
/*
* Modify data by XORing it with a special hash of salt.
*/
static SECStatus
oaep_xor_with_h1(unsigned char *data, unsigned int datalen,
unsigned char *salt, unsigned int saltlen)
{
SHA1Context *sha1cx;
unsigned char *dp, *dataend;
unsigned char end_octet;
sha1cx = SHA1_NewContext();
if (sha1cx == NULL) {
return SECFailure;
}
/*
* Get a hash of salt started; we will use it several times,
* adding in a different end octet (x00, x01, x02, ...).
*/
SHA1_Begin (sha1cx);
SHA1_Update (sha1cx, salt, saltlen);
end_octet = 0;
dp = data;
dataend = data + datalen;
while (dp < dataend) {
SHA1Context *sha1cx_h1;
unsigned int sha1len, sha1off;
unsigned char sha1[SHA1_LENGTH];
/*
* Create hash of (salt || end_octet)
*/
sha1cx_h1 = SHA1_CloneContext (sha1cx);
SHA1_Update (sha1cx_h1, &end_octet, 1);
SHA1_End (sha1cx_h1, sha1, &sha1len, sizeof(sha1));
SHA1_DestroyContext (sha1cx_h1, PR_TRUE);
PORT_Assert (sha1len == SHA1_LENGTH);
/*
* XOR that hash with the data.
* When we have fewer than SHA1_LENGTH octets of data
* left to xor, use just the low-order ones of the hash.
*/
sha1off = 0;
if ((dataend - dp) < SHA1_LENGTH)
sha1off = SHA1_LENGTH - (dataend - dp);
while (sha1off < SHA1_LENGTH)
*dp++ ^= sha1[sha1off++];
/*
* Bump for next hash chunk.
*/
end_octet++;
}
return SECSuccess;
}
/*
* Modify salt by XORing it with a special hash of data.
*/
static SECStatus
oaep_xor_with_h2(unsigned char *salt, unsigned int saltlen,
unsigned char *data, unsigned int datalen)
{
unsigned char sha1[SHA1_LENGTH];
unsigned char *psalt, *psha1, *saltend;
SECStatus rv;
/*
* Create a hash of data.
*/
rv = SHA1_HashBuf (sha1, data, datalen);
if (rv != SECSuccess) {
return rv;
}
/*
* XOR the low-order octets of that hash with salt.
*/
PORT_Assert (saltlen <= SHA1_LENGTH);
saltend = salt + saltlen;
psalt = salt;
psha1 = sha1 + SHA1_LENGTH - saltlen;
while (psalt < saltend) {
*psalt++ ^= *psha1++;
}
return SECSuccess;
}
/*
* Format one block of data for public/private key encryption using
* the rules defined in PKCS #1.
*/
static unsigned char *
rsa_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType,
SECItem *data)
{
unsigned char *block;
unsigned char *bp;
int padLen;
int i;
block = (unsigned char *) PORT_Alloc(modulusLen);
if (block == NULL)
return NULL;
bp = block;
/*
* All RSA blocks start with two octets:
* 0x00 || BlockType
*/
*bp++ = RSA_BLOCK_FIRST_OCTET;
*bp++ = (unsigned char) blockType;
switch (blockType) {
/*
* Blocks intended for private-key operation.
*/
case RSA_BlockPrivate0: /* essentially unused */
case RSA_BlockPrivate: /* preferred method */
/*
* 0x00 || BT || Pad || 0x00 || ActualData
* 1 1 padLen 1 data->len
* Pad is either all 0x00 or all 0xff bytes, depending on blockType.
*/
padLen = modulusLen - data->len - 3;
PORT_Assert (padLen >= RSA_BLOCK_MIN_PAD_LEN);
if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
PORT_Free (block);
return NULL;
}
PORT_Memset (bp,
blockType == RSA_BlockPrivate0
? RSA_BLOCK_PRIVATE0_PAD_OCTET
: RSA_BLOCK_PRIVATE_PAD_OCTET,
padLen);
bp += padLen;
*bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
PORT_Memcpy (bp, data->data, data->len);
break;
/*
* Blocks intended for public-key operation.
*/
case RSA_BlockPublic:
/*
* 0x00 || BT || Pad || 0x00 || ActualData
* 1 1 padLen 1 data->len
* Pad is all non-zero random bytes.
*/
padLen = modulusLen - data->len - 3;
PORT_Assert (padLen >= RSA_BLOCK_MIN_PAD_LEN);
if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
PORT_Free (block);
return NULL;
}
for (i = 0; i < padLen; i++) {
/* Pad with non-zero random data. */
do {
RNG_GenerateGlobalRandomBytes(bp + i, 1);
} while (bp[i] == RSA_BLOCK_AFTER_PAD_OCTET);
}
bp += padLen;
*bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
PORT_Memcpy (bp, data->data, data->len);
break;
/*
* Blocks intended for public-key operation, using
* Optimal Asymmetric Encryption Padding (OAEP).
*/
case RSA_BlockOAEP:
/*
* 0x00 || BT || Modified2(Salt) || Modified1(PaddedData)
* 1 1 OAEP_SALT_LEN OAEP_PAD_LEN + data->len [+ N]
*
* where:
* PaddedData is "Pad1 || ActualData [|| Pad2]"
* Salt is random data.
* Pad1 is all zeros.
* Pad2, if present, is random data.
* (The "modified" fields are all the same length as the original
* unmodified values; they are just xor'd with other values.)
*
* Modified1 is an XOR of PaddedData with a special octet
* string constructed of iterated hashing of Salt (see below).
* Modified2 is an XOR of Salt with the low-order octets of
* the hash of Modified1 (see farther below ;-).
*
* Whew!
*/
/*
* Salt
*/
RNG_GenerateGlobalRandomBytes(bp, OAEP_SALT_LEN);
bp += OAEP_SALT_LEN;
/*
* Pad1
*/
PORT_Memset (bp, OAEP_PAD_OCTET, OAEP_PAD_LEN);
bp += OAEP_PAD_LEN;
/*
* Data
*/
PORT_Memcpy (bp, data->data, data->len);
bp += data->len;
/*
* Pad2
*/
if (bp < (block + modulusLen))
RNG_GenerateGlobalRandomBytes(bp, block - bp + modulusLen);
/*
* Now we have the following:
* 0x00 || BT || Salt || PaddedData
* (From this point on, "Pad1 || Data [|| Pad2]" is treated
* as the one entity PaddedData.)
*
* We need to turn PaddedData into Modified1.
*/
if (oaep_xor_with_h1(block + 2 + OAEP_SALT_LEN,
modulusLen - 2 - OAEP_SALT_LEN,
block + 2, OAEP_SALT_LEN) != SECSuccess) {
PORT_Free (block);
return NULL;
}
/*
* Now we have:
* 0x00 || BT || Salt || Modified1(PaddedData)
*
* The remaining task is to turn Salt into Modified2.
*/
if (oaep_xor_with_h2(block + 2, OAEP_SALT_LEN,
block + 2 + OAEP_SALT_LEN,
modulusLen - 2 - OAEP_SALT_LEN) != SECSuccess) {
PORT_Free (block);
return NULL;
}
break;
default:
PORT_Assert (0);
PORT_Free (block);
return NULL;
}
return block;
}
static SECStatus
rsa_FormatBlock(SECItem *result, unsigned modulusLen,
RSA_BlockType blockType, SECItem *data)
{
/*
* XXX For now assume that the data length fits in a single
* XXX encryption block; the ASSERTs below force this.
* XXX To fix it, each case will have to loop over chunks whose
* XXX lengths satisfy the assertions, until all data is handled.
* XXX (Unless RSA has more to say about how to handle data
* XXX which does not fit in a single encryption block?)
* XXX And I do not know what the result is supposed to be,
* XXX so the interface to this function may need to change
* XXX to allow for returning multiple blocks, if they are
* XXX not wanted simply concatenated one after the other.
*/
switch (blockType) {
case RSA_BlockPrivate0:
case RSA_BlockPrivate:
case RSA_BlockPublic:
/*
* 0x00 || BT || Pad || 0x00 || ActualData
*
* The "3" below is the first octet + the second octet + the 0x00
* octet that always comes just before the ActualData.
*/
PORT_Assert (data->len <= (modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN)));
result->data = rsa_FormatOneBlock(modulusLen, blockType, data);
if (result->data == NULL) {
result->len = 0;
return SECFailure;
}
result->len = modulusLen;
break;
case RSA_BlockOAEP:
/*
* 0x00 || BT || M1(Salt) || M2(Pad1||ActualData[||Pad2])
*
* The "2" below is the first octet + the second octet.
* (The other fields do not contain the clear values, but are
* the same length as the clear values.)
*/
PORT_Assert (data->len <= (modulusLen - (2 + OAEP_SALT_LEN
+ OAEP_PAD_LEN)));
result->data = rsa_FormatOneBlock(modulusLen, blockType, data);
if (result->data == NULL) {
result->len = 0;
return SECFailure;
}
result->len = modulusLen;
break;
case RSA_BlockRaw:
/*
* Pad || ActualData
* Pad is zeros. The application is responsible for recovering
* the actual data.
*/
if (data->len > modulusLen ) {
return SECFailure;
}
result->data = (unsigned char*)PORT_ZAlloc(modulusLen);
result->len = modulusLen;
PORT_Memcpy(result->data+(modulusLen-data->len),data->data,data->len);
break;
default:
PORT_Assert (0);
result->data = NULL;
result->len = 0;
return SECFailure;
}
return SECSuccess;
}
/* XXX Doesn't set error code */
SECStatus
RSA_Sign(NSSLOWKEYPrivateKey *key,
unsigned char * output,
unsigned int * output_len,
unsigned int maxOutputLen,
unsigned char * input,
unsigned int input_len)
{
SECStatus rv = SECSuccess;
unsigned int modulus_len = nsslowkey_PrivateModulusLen(key);
SECItem formatted;
SECItem unformatted;
if (maxOutputLen < modulus_len)
return SECFailure;
PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
if (key->keyType != NSSLOWKEYRSAKey)
return SECFailure;
unformatted.len = input_len;
unformatted.data = input;
formatted.data = NULL;
rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockPrivate,
&unformatted);
if (rv != SECSuccess)
goto done;
rv = RSA_PrivateKeyOpDoubleChecked(&key->u.rsa, output, formatted.data);
*output_len = modulus_len;
goto done;
done:
if (formatted.data != NULL)
PORT_ZFree(formatted.data, modulus_len);
return rv;
}
/* XXX Doesn't set error code */
SECStatus
RSA_CheckSign(NSSLOWKEYPublicKey *key,
unsigned char * sign,
unsigned int sign_len,
unsigned char * hash,
unsigned int hash_len)
{
SECStatus rv;
unsigned int modulus_len = nsslowkey_PublicModulusLen(key);
unsigned int i;
unsigned char * buffer;
modulus_len = nsslowkey_PublicModulusLen(key);
if (sign_len != modulus_len)
goto failure;
if (hash_len > modulus_len - 8)
goto failure;
PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
buffer = (unsigned char *)PORT_Alloc(modulus_len + 1);
if (!buffer)
goto failure;
rv = RSA_PublicKeyOp(&key->u.rsa, buffer, sign);
if (rv != SECSuccess)
goto loser;
/*
* check the padding that was used
*/
if (buffer[0] != 0 || buffer[1] != 1)
goto loser;
for (i = 2; i < modulus_len - hash_len - 1; i++) {
if (buffer[i] == 0)
break;
if (buffer[i] != 0xff)
goto loser;
}
/*
* make sure we get the same results
*/
if (PORT_Memcmp(buffer + modulus_len - hash_len, hash, hash_len) != 0)
goto loser;
PORT_Free(buffer);
return SECSuccess;
loser:
PORT_Free(buffer);
failure:
return SECFailure;
}
/* XXX Doesn't set error code */
SECStatus
RSA_CheckSignRecover(NSSLOWKEYPublicKey *key,
unsigned char * data,
unsigned int * data_len,
unsigned int max_output_len,
unsigned char * sign,
unsigned int sign_len)
{
SECStatus rv;
unsigned int modulus_len = nsslowkey_PublicModulusLen(key);
unsigned int i;
unsigned char * buffer;
if (sign_len != modulus_len)
goto failure;
PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
buffer = (unsigned char *)PORT_Alloc(modulus_len + 1);
if (!buffer)
goto failure;
rv = RSA_PublicKeyOp(&key->u.rsa, buffer, sign);
if (rv != SECSuccess)
goto loser;
*data_len = 0;
/*
* check the padding that was used
*/
if (buffer[0] != 0 || buffer[1] != 1)
goto loser;
for (i = 2; i < modulus_len; i++) {
if (buffer[i] == 0) {
*data_len = modulus_len - i - 1;
break;
}
if (buffer[i] != 0xff)
goto loser;
}
if (*data_len == 0)
goto loser;
if (*data_len > max_output_len)
goto loser;
/*
* make sure we get the same results
*/
PORT_Memcpy(data,buffer + modulus_len - *data_len, *data_len);
PORT_Free(buffer);
return SECSuccess;
loser:
PORT_Free(buffer);
failure:
return SECFailure;
}
/* XXX Doesn't set error code */
SECStatus
RSA_EncryptBlock(NSSLOWKEYPublicKey *key,
unsigned char * output,
unsigned int * output_len,
unsigned int max_output_len,
unsigned char * input,
unsigned int input_len)
{
SECStatus rv;
unsigned int modulus_len = nsslowkey_PublicModulusLen(key);
SECItem formatted;
SECItem unformatted;
formatted.data = NULL;
if (max_output_len < modulus_len)
goto failure;
PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
unformatted.len = input_len;
unformatted.data = input;
formatted.data = NULL;
rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockPublic,
&unformatted);
if (rv != SECSuccess)
goto failure;
rv = RSA_PublicKeyOp(&key->u.rsa, output, formatted.data);
if (rv != SECSuccess)
goto failure;
PORT_ZFree(formatted.data, modulus_len);
*output_len = modulus_len;
return SECSuccess;
failure:
if (formatted.data != NULL)
PORT_ZFree(formatted.data, modulus_len);
return SECFailure;
}
/* XXX Doesn't set error code */
SECStatus
RSA_DecryptBlock(NSSLOWKEYPrivateKey *key,
unsigned char * output,
unsigned int * output_len,
unsigned int max_output_len,
unsigned char * input,
unsigned int input_len)
{
SECStatus rv;
unsigned int modulus_len = nsslowkey_PrivateModulusLen(key);
unsigned int i;
unsigned char * buffer;
PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
if (input_len != modulus_len)
goto failure;
buffer = (unsigned char *)PORT_Alloc(modulus_len + 1);
if (!buffer)
goto failure;
rv = RSA_PrivateKeyOp(&key->u.rsa, buffer, input);
if (rv != SECSuccess)
goto loser;
if (buffer[0] != 0 || buffer[1] != 2)
goto loser;
*output_len = 0;
for (i = 2; i < modulus_len; i++) {
if (buffer[i] == 0) {
*output_len = modulus_len - i - 1;
break;
}
}
if (*output_len == 0)
goto loser;
if (*output_len > max_output_len)
goto loser;
PORT_Memcpy(output, buffer + modulus_len - *output_len, *output_len);
PORT_Free(buffer);
return SECSuccess;
loser:
PORT_Free(buffer);
failure:
return SECFailure;
}
/* XXX Doesn't set error code */
/*
* added to make pkcs #11 happy
* RAW is RSA_X_509
*/
SECStatus
RSA_SignRaw(NSSLOWKEYPrivateKey *key,
unsigned char * output,
unsigned int * output_len,
unsigned int maxOutputLen,
unsigned char * input,
unsigned int input_len)
{
SECStatus rv = SECSuccess;
unsigned int modulus_len = nsslowkey_PrivateModulusLen(key);
SECItem formatted;
SECItem unformatted;
if (maxOutputLen < modulus_len)
return SECFailure;
PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
if (key->keyType != NSSLOWKEYRSAKey)
return SECFailure;
unformatted.len = input_len;
unformatted.data = input;
formatted.data = NULL;
rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockRaw, &unformatted);
if (rv != SECSuccess)
goto done;
rv = RSA_PrivateKeyOpDoubleChecked(&key->u.rsa, output, formatted.data);
*output_len = modulus_len;
done:
if (formatted.data != NULL)
PORT_ZFree(formatted.data, modulus_len);
return rv;
}
/* XXX Doesn't set error code */
SECStatus
RSA_CheckSignRaw(NSSLOWKEYPublicKey *key,
unsigned char * sign,
unsigned int sign_len,
unsigned char * hash,
unsigned int hash_len)
{
SECStatus rv;
unsigned int modulus_len = nsslowkey_PublicModulusLen(key);
unsigned char * buffer;
if (sign_len != modulus_len)
goto failure;
if (hash_len > modulus_len)
goto failure;
PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
buffer = (unsigned char *)PORT_Alloc(modulus_len + 1);
if (!buffer)
goto failure;
rv = RSA_PublicKeyOp(&key->u.rsa, buffer, sign);
if (rv != SECSuccess)
goto loser;
/*
* make sure we get the same results
*/
/* NOTE: should we verify the leading zeros? */
if (PORT_Memcmp(buffer + (modulus_len-hash_len), hash, hash_len) != 0)
goto loser;
PORT_Free(buffer);
return SECSuccess;
loser:
PORT_Free(buffer);
failure:
return SECFailure;
}
/* XXX Doesn't set error code */
SECStatus
RSA_CheckSignRecoverRaw(NSSLOWKEYPublicKey *key,
unsigned char * data,
unsigned int * data_len,
unsigned int max_output_len,
unsigned char * sign,
unsigned int sign_len)
{
SECStatus rv;
unsigned int modulus_len = nsslowkey_PublicModulusLen(key);
if (sign_len != modulus_len)
goto failure;
if (max_output_len < modulus_len)
goto failure;
PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
rv = RSA_PublicKeyOp(&key->u.rsa, data, sign);
if (rv != SECSuccess)
goto failure;
*data_len = modulus_len;
return SECSuccess;
failure:
return SECFailure;
}
/* XXX Doesn't set error code */
SECStatus
RSA_EncryptRaw(NSSLOWKEYPublicKey *key,
unsigned char * output,
unsigned int * output_len,
unsigned int max_output_len,
unsigned char * input,
unsigned int input_len)
{
SECStatus rv;
unsigned int modulus_len = nsslowkey_PublicModulusLen(key);
SECItem formatted;
SECItem unformatted;
formatted.data = NULL;
if (max_output_len < modulus_len)
goto failure;
PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
unformatted.len = input_len;
unformatted.data = input;
formatted.data = NULL;
rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockRaw, &unformatted);
if (rv != SECSuccess)
goto failure;
rv = RSA_PublicKeyOp(&key->u.rsa, output, formatted.data);
if (rv != SECSuccess)
goto failure;
PORT_ZFree(formatted.data, modulus_len);
*output_len = modulus_len;
return SECSuccess;
failure:
if (formatted.data != NULL)
PORT_ZFree(formatted.data, modulus_len);
return SECFailure;
}
/* XXX Doesn't set error code */
SECStatus
RSA_DecryptRaw(NSSLOWKEYPrivateKey *key,
unsigned char * output,
unsigned int * output_len,
unsigned int max_output_len,
unsigned char * input,
unsigned int input_len)
{
SECStatus rv;
unsigned int modulus_len = nsslowkey_PrivateModulusLen(key);
if (modulus_len <= 0)
goto failure;
if (modulus_len > max_output_len)
goto failure;
PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
if (key->keyType != NSSLOWKEYRSAKey)
goto failure;
if (input_len != modulus_len)
goto failure;
rv = RSA_PrivateKeyOp(&key->u.rsa, output, input);
if (rv != SECSuccess)
goto failure;
*output_len = modulus_len;
return SECSuccess;
failure:
return SECFailure;
}

View File

@@ -1,56 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* Library identity and versioning */
#include "nss.h"
#if defined(DEBUG)
#define _DEBUG_STRING " (debug)"
#else
#define _DEBUG_STRING ""
#endif
/*
* Version information for the 'ident' and 'what commands
*
* NOTE: the first component of the concatenated rcsid string
* must not end in a '$' to prevent rcs keyword substitution.
*/
const char __nss_softokn_rcsid[] = "$Header: NSS " NSS_VERSION _DEBUG_STRING
" " __DATE__ " " __TIME__ " $";
const char __nss_softokn_sccsid[] = "@(#)NSS " NSS_VERSION _DEBUG_STRING
" " __DATE__ " " __TIME__;

View File

@@ -1,164 +0,0 @@
/*
* softoken.h - private data structures and prototypes for the softoken lib
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: softoken.h,v 1.7 2005-03-29 18:21:18 nelsonb%netscape.com Exp $ */
#ifndef _SOFTOKEN_H_
#define _SOFTOKEN_H_
#include "blapi.h"
#include "lowkeyti.h"
#include "softoknt.h"
#include "secoidt.h"
#include "pkcs11t.h" /* CK_RV Required for sftk_fipsPowerUpSelfTest(). */
SEC_BEGIN_PROTOS
/*
** RSA encryption/decryption. When encrypting/decrypting the output
** buffer must be at least the size of the public key modulus.
*/
/*
** Format some data into a PKCS#1 encryption block, preparing the
** data for RSA encryption.
** "result" where the formatted block is stored (memory is allocated)
** "modulusLen" the size of the formatted block
** "blockType" what block type to use (SEC_RSABlock*)
** "data" the data to format
*/
extern SECStatus RSA_FormatBlock(SECItem *result,
unsigned int modulusLen,
RSA_BlockType blockType,
SECItem *data);
/*
** Similar, but just returns a pointer to the allocated memory, *and*
** will *only* format one block, even if we (in the future) modify
** RSA_FormatBlock() to loop over multiples of modulusLen.
*/
extern unsigned char *RSA_FormatOneBlock(unsigned int modulusLen,
RSA_BlockType blockType,
SECItem *data);
/*
* convenience wrappers for doing single RSA operations. They create the
* RSA context internally and take care of the formatting
* requirements. Blinding happens automagically within RSA_SignHash and
* RSA_DecryptBlock.
*/
extern
SECStatus RSA_Sign(NSSLOWKEYPrivateKey *key, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
unsigned char *input, unsigned int inputLen);
extern
SECStatus RSA_CheckSign(NSSLOWKEYPublicKey *key, unsigned char *sign,
unsigned int signLength, unsigned char *hash,
unsigned int hashLength);
extern
SECStatus RSA_CheckSignRecover(NSSLOWKEYPublicKey *key, unsigned char *data,
unsigned int *data_len,unsigned int max_output_len,
unsigned char *sign, unsigned int sign_len);
extern
SECStatus RSA_EncryptBlock(NSSLOWKEYPublicKey *key, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
unsigned char *input, unsigned int inputLen);
extern
SECStatus RSA_DecryptBlock(NSSLOWKEYPrivateKey *key, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
unsigned char *input, unsigned int inputLen);
/*
* added to make pkcs #11 happy
* RAW is RSA_X_509
*/
extern
SECStatus RSA_SignRaw( NSSLOWKEYPrivateKey *key, unsigned char *output,
unsigned int *output_len, unsigned int maxOutputLen,
unsigned char *input, unsigned int input_len);
extern
SECStatus RSA_CheckSignRaw( NSSLOWKEYPublicKey *key, unsigned char *sign,
unsigned int sign_len, unsigned char *hash,
unsigned int hash_len);
extern
SECStatus RSA_CheckSignRecoverRaw( NSSLOWKEYPublicKey *key, unsigned char *data,
unsigned int *data_len, unsigned int max_output_len,
unsigned char *sign, unsigned int sign_len);
extern
SECStatus RSA_EncryptRaw( NSSLOWKEYPublicKey *key, unsigned char *output,
unsigned int *output_len,
unsigned int max_output_len,
unsigned char *input, unsigned int input_len);
extern
SECStatus RSA_DecryptRaw(NSSLOWKEYPrivateKey *key, unsigned char *output,
unsigned int *output_len,
unsigned int max_output_len,
unsigned char *input, unsigned int input_len);
/*
** Prepare a buffer for DES encryption, growing to the appropriate boundary,
** filling with the appropriate padding.
** We add from 1 to DES_KEY_LENGTH bytes -- we *always* grow.
** The extra bytes contain the value of the length of the padding:
** if we have 2 bytes of padding, then the padding is "0x02, 0x02".
**
** NOTE: If arena is non-NULL, we re-allocate from there, otherwise
** we assume (and use) PR memory (re)allocation.
** Maybe this belongs in util?
*/
extern unsigned char * DES_PadBuffer(PRArenaPool *arena, unsigned char *inbuf,
unsigned int inlen, unsigned int *outlen);
/****************************************/
/*
** Power-Up selftests required for FIPS and invoked only
** under PKCS #11 FIPS mode.
*/
extern CK_RV sftk_fipsPowerUpSelfTest( void );
/*
** make known fixed PKCS #11 key types to their sizes in bytes
*/
unsigned long sftk_MapKeySize(CK_KEY_TYPE keyType);
SEC_END_PROTOS
#endif /* _SOFTOKEN_H_ */

View File

@@ -1,61 +0,0 @@
;+#
;+# ***** BEGIN LICENSE BLOCK *****
;+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
;+#
;+# The contents of this file are subject to the Mozilla Public License Version
;+# 1.1 (the "License"); you may not use this file except in compliance with
;+# the License. You may obtain a copy of the License at
;+# http://www.mozilla.org/MPL/
;+#
;+# Software distributed under the License is distributed on an "AS IS" basis,
;+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
;+# for the specific language governing rights and limitations under the
;+# License.
;+#
;+# The Original Code is the Netscape security libraries.
;+#
;+# The Initial Developer of the Original Code is
;+# Netscape Communications Corporation.
;+# Portions created by the Initial Developer are Copyright (C) 2000
;+# the Initial Developer. All Rights Reserved.
;+#
;+# Contributor(s):
;+# Dr Stephen Henson <stephen.henson@gemplus.com>
;+#
;+# Alternatively, the contents of this file may be used under the terms of
;+# either the GNU General Public License Version 2 or later (the "GPL"), or
;+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
;+# in which case the provisions of the GPL or the LGPL are applicable instead
;+# of those above. If you wish to allow use of your version of this file only
;+# under the terms of either the GPL or the LGPL, and not to allow others to
;+# use your version of this file under the terms of the MPL, indicate your
;+# decision by deleting the provisions above and replace them with the notice
;+# and other provisions required by the GPL or the LGPL. If you do not delete
;+# the provisions above, a recipient may use your version of this file under
;+# the terms of any one of the MPL, the GPL or the LGPL.
;+#
;+# ***** END LICENSE BLOCK *****
;+#
;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
;+# 1. For all unix platforms, the string ";-" means "remove this line"
;+# 2. For all unix platforms, the string " DATA " will be removed from any
;+# line on which it occurs.
;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
;+# On AIX, lines containing ";+" will be removed.
;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
;+# 5. For all unix platforms, after the above processing has taken place,
;+# all characters after the first ";" on the line will be removed.
;+# And for AIX, the first ";" will also be removed.
;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
;+# directives are hidden behind ";", ";+", and ";-"
;+NSS_3.4 { # NSS 3.4 release
;+ global:
LIBRARY softokn3 ;-
EXPORTS ;-
C_GetFunctionList; Make this function like a real PKCS #11 module as well
FC_GetFunctionList;
NSC_GetFunctionList;
NSC_ModuleDBFunc;
;+ local:
;+ *;
;+};

Some files were not shown because too many files have changed in this diff Show More