Id repo_add_haiku_package(Repo *repo, const char *hpkgPath, int flags) { BPackageInfo packageInfo; if (packageInfo.ReadFromPackageFile(hpkgPath) != B_OK) return 0; return repo_add_haiku_package_info(repo, packageInfo, flags); }
virtual void OnPackageAdded(const BPackageInfo& packageInfo) { if (fQuiet) return; printf("%s (%s)\n", packageInfo.Name().String(), packageInfo.Version().ToString().String()); if (fVerbose) { printf("\tsummary: %s\n", packageInfo.Summary().String()); printf("\tvendor: %s\n", packageInfo.Vendor().String()); printf("\tpackager: %s\n", packageInfo.Packager().String()); printf("\tchecksum: %s\n", packageInfo.Checksum().String()); if (uint32 flags = packageInfo.Flags()) { printf("\tflags:\n"); if ((flags & B_PACKAGE_FLAG_APPROVE_LICENSE) != 0) printf("\t\tapprove_license\n"); if ((flags & B_PACKAGE_FLAG_SYSTEM_PACKAGE) != 0) printf("\t\tsystem_package\n"); } } else printf("\tchecksum: %s\n", packageInfo.Checksum().String()); }
int32 BPackageManager::_FindBasePackage(const PackageList& packages, const BPackageInfo& info) { if (info.BasePackage().IsEmpty()) return -1; // find the requirement matching the base package BPackageResolvableExpression* basePackage = NULL; int32 count = info.RequiresList().CountItems(); for (int32 i = 0; i < count; i++) { BPackageResolvableExpression* requires = info.RequiresList().ItemAt(i); if (requires->Name() == info.BasePackage()) { basePackage = requires; break; } } if (basePackage == NULL) { fUserInteractionHandler->Warn(B_OK, "package %s-%s doesn't have a " "matching requires for its base package \"%s\"", info.Name().String(), info.Version().ToString().String(), info.BasePackage().String()); return -1; } // find the first package matching the base package requires count = packages.CountItems(); for (int32 i = 0; i < count; i++) { BSolverPackage* package = packages.ItemAt(i); if (package->Name() == basePackage->Name() && package->Info().Matches(*basePackage)) { return i; } } return -1; }
static Id add_package_info_to_repo(Repo *repo, Repodata *repoData, const BPackageInfo &packageInfo) { Pool *pool = repo->pool; Id solvableId = repo_add_solvable(repo); Solvable *solvable = pool_id2solvable(pool, solvableId); // Prepend "pkg:" to package name, so "provides" don't match unless explicitly // specified this way. BString name("pkg:"); name << packageInfo.Name(); solvable->name = pool_str2id(pool, name, 1); if (packageInfo.Architecture() == B_PACKAGE_ARCHITECTURE_ANY) solvable->arch = ARCH_ANY; else if (packageInfo.Architecture() == B_PACKAGE_ARCHITECTURE_SOURCE) solvable->arch = ARCH_SRC; else solvable->arch = pool_str2id(pool, BPackageInfo::kArchitectureNames[packageInfo.Architecture()], 1); solvable->evr = pool_str2id(pool, packageInfo.Version().ToString(), 1); solvable->vendor = pool_str2id(pool, packageInfo.Vendor(), 1); repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_SUMMARY, packageInfo.Summary()); repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_DESCRIPTION, packageInfo.Description()); repodata_set_str(repoData, solvable - pool->solvables, SOLVABLE_PACKAGER, packageInfo.Packager()); if (!packageInfo.Checksum().IsEmpty()) repodata_set_checksum(repoData, solvable - pool->solvables, SOLVABLE_CHECKSUM, REPOKEY_TYPE_SHA256, packageInfo.Checksum()); solvable->provides = repo_addid_dep(repo, solvable->provides, pool_rel2id(pool, solvable->name, solvable->evr, REL_EQ, 1), 0); add_resolvables(repo, solvable->provides, packageInfo.ProvidesList()); add_resolvable_expressions(repo, solvable->requires, packageInfo.RequiresList()); add_resolvable_expressions(repo, solvable->supplements, packageInfo.SupplementsList()); add_resolvable_expressions(repo, solvable->conflicts, packageInfo.ConflictsList()); add_resolvable_expressions(repo, solvable->enhances, packageInfo.FreshensList()); add_replaces_list(repo, solvable->obsoletes, packageInfo.ReplacesList()); // TODO: Check whether freshens and replaces does indeed work as intended // here. // TODO: copyrights, licenses, URLs, source URLs return solvableId; }
void WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList, const BPackageInfo& packageInfo) { // name AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME, packageInfo.Name(), attributeList); // summary AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY, packageInfo.Summary(), attributeList); // description AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION, packageInfo.Description(), attributeList); // vendor AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR, packageInfo.Vendor(), attributeList); // packager AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER, packageInfo.Packager(), attributeList); // base package (optional) _AddStringAttributeIfNotEmpty(B_HPKG_ATTRIBUTE_ID_PACKAGE_BASE_PACKAGE, packageInfo.BasePackage(), attributeList); // flags PackageAttribute* flags = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS, B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT); flags->unsignedInt = packageInfo.Flags(); attributeList.Add(flags); // architecture PackageAttribute* architecture = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE, B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); architecture->unsignedInt = packageInfo.Architecture(); attributeList.Add(architecture); // version RegisterPackageVersion(attributeList, packageInfo.Version()); // copyright list _AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT, packageInfo.CopyrightList(), attributeList); // license list _AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE, packageInfo.LicenseList(), attributeList); // URL list _AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_URL, packageInfo.URLList(), attributeList); // source URL list _AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL, packageInfo.SourceURLList(), attributeList); // provides list const BObjectList<BPackageResolvable>& providesList = packageInfo.ProvidesList(); for (int i = 0; i < providesList.CountItems(); ++i) { BPackageResolvable* resolvable = providesList.ItemAt(i); bool hasVersion = resolvable->Version().InitCheck() == B_OK; bool hasCompatibleVersion = resolvable->CompatibleVersion().InitCheck() == B_OK; PackageAttribute* provides = AddStringAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES, resolvable->Name(), attributeList); if (hasVersion) RegisterPackageVersion(provides->children, resolvable->Version()); if (hasCompatibleVersion) { RegisterPackageVersion(provides->children, resolvable->CompatibleVersion(), B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_COMPATIBLE); } } // requires list RegisterPackageResolvableExpressionList(attributeList, packageInfo.RequiresList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES); // supplements list RegisterPackageResolvableExpressionList(attributeList, packageInfo.SupplementsList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS); // conflicts list RegisterPackageResolvableExpressionList(attributeList, packageInfo.ConflictsList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS); // freshens list RegisterPackageResolvableExpressionList(attributeList, packageInfo.FreshensList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS); // replaces list _AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES, packageInfo.ReplacesList(), attributeList); // global writable file info list const BObjectList<BGlobalWritableFileInfo>& globalWritableFileInfos = packageInfo.GlobalWritableFileInfos(); for (int32 i = 0; i < globalWritableFileInfos.CountItems(); ++i) { BGlobalWritableFileInfo* info = globalWritableFileInfos.ItemAt(i); PackageAttribute* attribute = AddStringAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_GLOBAL_WRITABLE_FILE, info->Path(), attributeList); if (info->IsDirectory()) { PackageAttribute* isDirectoryAttribute = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY, B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); isDirectoryAttribute->unsignedInt = 1; attribute->children.Add(isDirectoryAttribute); } if (info->IsIncluded()) { PackageAttribute* updateTypeAttribute = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_WRITABLE_FILE_UPDATE_TYPE, B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); updateTypeAttribute->unsignedInt = info->UpdateType(); attribute->children.Add(updateTypeAttribute); } } // user settings file info list const BObjectList<BUserSettingsFileInfo>& userSettingsFileInfos = packageInfo.UserSettingsFileInfos(); for (int32 i = 0; i < userSettingsFileInfos.CountItems(); ++i) { BUserSettingsFileInfo* info = userSettingsFileInfos.ItemAt(i); PackageAttribute* attribute = AddStringAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SETTINGS_FILE, info->Path(), attributeList); if (info->IsDirectory()) { PackageAttribute* isDirectoryAttribute = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY, B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); isDirectoryAttribute->unsignedInt = 1; attribute->children.Add(isDirectoryAttribute); } else { _AddStringAttributeIfNotEmpty( B_HPKG_ATTRIBUTE_ID_PACKAGE_SETTINGS_FILE_TEMPLATE, info->TemplatePath(), attribute->children); } } // user list const BObjectList<BUser>& users = packageInfo.Users(); for (int32 i = 0; i < users.CountItems(); ++i) { const BUser* user = users.ItemAt(i); PackageAttribute* attribute = AddStringAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_USER, user->Name(), attributeList); _AddStringAttributeIfNotEmpty( B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_REAL_NAME, user->RealName(), attribute->children); _AddStringAttributeIfNotEmpty( B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_HOME, user->Home(), attribute->children); _AddStringAttributeIfNotEmpty( B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SHELL, user->Shell(), attribute->children); for (int32 k = 0; k < user->Groups().CountStrings(); k++) { AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_GROUP, user->Groups().StringAt(k), attribute->children); } } // group list _AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_GROUP, packageInfo.Groups(), attributeList); // post install script list _AddStringAttributeList(B_HPKG_ATTRIBUTE_ID_PACKAGE_POST_INSTALL_SCRIPT, packageInfo.PostInstallScripts(), attributeList); // checksum (optional, only exists in repositories) _AddStringAttributeIfNotEmpty(B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM, packageInfo.Checksum(), attributeList); // install path (optional) _AddStringAttributeIfNotEmpty(B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH, packageInfo.InstallPath(), attributeList); }
status_t BPackageRoster::GetActivePackages(BPackageInstallationLocation location, BPackageInfoSet& packageInfos) { // This method makes sense only on an installed Haiku, but not for the build // tools. #if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU) // check the given location directory_which packagesDirectory; switch (location) { case B_PACKAGE_INSTALLATION_LOCATION_SYSTEM: packagesDirectory = B_SYSTEM_PACKAGES_DIRECTORY; break; case B_PACKAGE_INSTALLATION_LOCATION_COMMON: packagesDirectory = B_COMMON_PACKAGES_DIRECTORY; break; case B_PACKAGE_INSTALLATION_LOCATION_HOME: packagesDirectory = B_USER_PACKAGES_DIRECTORY; break; default: return B_BAD_VALUE; } // find the package links directory BPath packageLinksPath; status_t error = find_directory(B_PACKAGE_LINKS_DIRECTORY, &packageLinksPath); if (error != B_OK) return error; // find and open the packages directory BPath packagesDirPath; error = find_directory(packagesDirectory, &packagesDirPath); if (error != B_OK) return error; BDirectory directory; error = directory.SetTo(packagesDirPath.Path()); if (error != B_OK) return error; // TODO: Implement that correctly be reading the activation files/directory! // iterate through the packages char buffer[sizeof(dirent) + B_FILE_NAME_LENGTH]; dirent* entry = (dirent*)&buffer; while (directory.GetNextDirents(entry, sizeof(buffer), 1) == 1) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; // get the full package file path BPath packagePath; error = packagePath.SetTo(packagesDirPath.Path(), entry->d_name); if (error != B_OK) continue; // read the package info from the file BPackageReader packageReader(NULL); error = packageReader.Init(packagePath.Path()); if (error != B_OK) continue; BPackageInfo info; BPackageInfoContentHandler handler(info); error = packageReader.ParseContent(&handler); if (error != B_OK || info.InitCheck() != B_OK) continue; // check whether the package is really active by verifying that a // package link exists for it BString packageLinkName(info.Name()); packageLinkName << '-' << info.Version().ToString(); BPath packageLinkPath; struct stat st; if (packageLinkPath.SetTo(packageLinksPath.Path(), packageLinkName) != B_OK || lstat(packageLinkPath.Path(), &st) != 0) { continue; } // add the info error = packageInfos.AddInfo(info); if (error != B_OK) return error; } return B_OK; #else return B_NOT_SUPPORTED; #endif }
int main(int argc, const char* const* argv) { if (argc != 3) print_usage_and_exit(true); if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) print_usage_and_exit(false); const char* const packageInfoPath = argv[1]; const char* const repositoryCachePath = argv[2]; // read the repository cache BRepositoryCache repositoryCache; status_t error = repositoryCache.SetTo(repositoryCachePath); if (error != B_OK) { DIE(error, "failed to read repository cache file \"%s\"", repositoryCachePath); } // create a map for all provides (name -> resolvable list) typedef std::map<BString, ProvidesList> ProvidesMap; ProvidesMap providesMap; for (BRepositoryCache::Iterator it = repositoryCache.GetIterator(); const BPackageInfo* info = it.Next();) { const BObjectList<BPackageResolvable>& provides = info->ProvidesList(); int32 count = provides.CountItems(); for (int32 i = 0; i < count; i++) { BPackageResolvable* resolvable = provides.ItemAt(i); ProvidesList& providesList = providesMap[resolvable->Name()]; providesList.push_back(resolvable); } } // load the package info BPackageInfo packageInfo; error = packageInfo.ReadFromConfigFile(packageInfoPath); if (error != B_OK) DIE(error, "failed to read package info file \"%s\"", packageInfoPath); // clone the package info's requires list typedef std::list<BPackageResolvableExpression> RequiresList; RequiresList requiresList; int32 requiresCount = packageInfo.RequiresList().CountItems(); for (int32 i = 0; i < requiresCount; i++) requiresList.push_back(*packageInfo.RequiresList().ItemAt(i)); // rebuild the requires list with updated versions packageInfo.ClearRequiresList(); for (RequiresList::iterator it = requiresList.begin(); it != requiresList.end(); ++it) { BPackageResolvableExpression expression = *it; ProvidesMap::iterator foundIt = providesMap.find(expression.Name()); if (foundIt != providesMap.end()) update_requires_expression(expression, foundIt->second); error = packageInfo.AddRequires(expression); if (error != B_OK) DIE(error, "failed to add requires item to package info"); } // write updated package info BString configString; error = packageInfo.GetConfigString(configString); if (error != B_OK) DIE(error, "failed to get updated package info string"); FILE* file = fopen(packageInfoPath, "w"); if (file == NULL) { DIE(errno, "failed to open package info file \"%s\" for writing", packageInfoPath); } if (fwrite(configString.String(), configString.Length(), 1, file) != 1) { DIE(errno, "failed to write updated package info file \"%s\"", packageInfoPath); } fclose(file); return 0; }
void WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList, const BPackageInfo& packageInfo) { // name PackageAttribute* name = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); name->string = fPackageStringCache.Get(packageInfo.Name().String()); attributeList.Add(name); // summary PackageAttribute* summary = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); summary->string = fPackageStringCache.Get(packageInfo.Summary().String()); attributeList.Add(summary); // description PackageAttribute* description = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); description->string = fPackageStringCache.Get(packageInfo.Description().String()); attributeList.Add(description); // vendor PackageAttribute* vendor = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); vendor->string = fPackageStringCache.Get(packageInfo.Vendor().String()); attributeList.Add(vendor); // packager PackageAttribute* packager = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); packager->string = fPackageStringCache.Get(packageInfo.Packager().String()); attributeList.Add(packager); // flags PackageAttribute* flags = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS, B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT); flags->unsignedInt = packageInfo.Flags(); attributeList.Add(flags); // architecture PackageAttribute* architecture = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE, B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); architecture->unsignedInt = packageInfo.Architecture(); attributeList.Add(architecture); // version RegisterPackageVersion(attributeList, packageInfo.Version()); // copyright list const BObjectList<BString>& copyrightList = packageInfo.CopyrightList(); for (int i = 0; i < copyrightList.CountItems(); ++i) { PackageAttribute* copyright = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); copyright->string = fPackageStringCache.Get(copyrightList.ItemAt(i)->String()); attributeList.Add(copyright); } // license list const BObjectList<BString>& licenseList = packageInfo.LicenseList(); for (int i = 0; i < licenseList.CountItems(); ++i) { PackageAttribute* license = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); license->string = fPackageStringCache.Get(licenseList.ItemAt(i)->String()); attributeList.Add(license); } // provides list const BObjectList<BPackageResolvable>& providesList = packageInfo.ProvidesList(); for (int i = 0; i < providesList.CountItems(); ++i) { BPackageResolvable* resolvable = providesList.ItemAt(i); bool hasVersion = resolvable->Version().InitCheck() == B_OK; PackageAttribute* provides = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); provides->string = fPackageStringCache.Get(resolvable->Name().String()); attributeList.Add(provides); PackageAttribute* providesType = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_TYPE, B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); providesType->unsignedInt = resolvable->Type(); provides->children.Add(providesType); if (hasVersion) RegisterPackageVersion(provides->children, resolvable->Version()); } // requires list RegisterPackageResolvableExpressionList(attributeList, packageInfo.RequiresList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES); // supplements list RegisterPackageResolvableExpressionList(attributeList, packageInfo.SupplementsList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS); // conflicts list RegisterPackageResolvableExpressionList(attributeList, packageInfo.ConflictsList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS); // freshens list RegisterPackageResolvableExpressionList(attributeList, packageInfo.FreshensList(), B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS); // replaces list const BObjectList<BString>& replacesList = packageInfo.ReplacesList(); for (int i = 0; i < replacesList.CountItems(); ++i) { PackageAttribute* replaces = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); replaces->string = fPackageStringCache.Get(replacesList.ItemAt(i)->String()); attributeList.Add(replaces); } // checksum (optional, only exists in repositories) if (packageInfo.Checksum().Length() > 0) { PackageAttribute* checksum = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); checksum->string = fPackageStringCache.Get(packageInfo.Checksum().String()); attributeList.Add(checksum); } }