#!/usr/local/bin/python # SUSfL (SUS for Linux) is a clean room implementation of SUS running under Linux. # Copyright (C) 2004 Vladimir Umnov # # This file is part of SUSfL. # # SUSfL is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # SUSfL is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Foobar; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #TODO: restructure loaditems and rename to settables, update may fail if download in progress #import site #site.encoding = 'utf-8' #from mod_python import apache import sys, time, os import xml.dom.minidom import string from sus_consts import * from sus_utils import * req = sys.stdout #problematic global variables last_sProviderID = "" bMaintainContentLocally = True #Empty catalog on errors def ReturnEmptyCatalog(req): req.write("") return 0 # return apache.OK def DoProvidersQuery(req): req.write("""ProvidersProvider""") providers = {} for line in open(providers_file, "rt").readlines(): pos = string.find(line, ',') if pos > 0: providers[line[:pos]] = string.split(string.strip(line[pos+1:]), '@|') for key in providers.keys(): req.write("""com.microsoft%s"""% \ (key, key, providers[key][conFieldProviderDetection])) req.write("") def DoProductsQuery(req, query): products_query = [] for node in query.childNodes: if node.nodeName == 'parentItems': for cnode in node.childNodes: if cnode.nodeName == 'item': data = "" for tn in cnode.childNodes: if tn.nodeType == tn.TEXT_NODE: data = data + tn.data data = string.strip(data) if data <> "": products_query.append(data) if products_query == []: return ReturnEmptyCatalog(req) req.write ("") products = {} for product in products_query: for line in open(products_file%(product,), "rt").readlines(): pos = string.find(line, ',') if pos > 0: products[line[:pos]] = string.split(string.strip(line[pos+1:]), '@|') providers = {} for line in open(providers_file, "rt").readlines(): pos = string.find(line, ',') if pos > 0: providers[line[:pos]] = string.split(string.strip(line[pos+1:]), '@|') for oProviderID in products_query: sProviderID = oProviderID req.write ("""com.microsoft"""% \ (EncodeValue(sProviderID), EncodeValue(sProviderID))) if providers.has_key(sProviderID): sProductIDs = providers[sProviderID][conFieldProviderProducts] aProductIDs = string.split(sProductIDs, ",") for sProductID in aProductIDs: sCombinedProductID = sProviderID + "." + sProductID if products.has_key(sCombinedProductID): aFields = products[sCombinedProductID] req.write("""%s%s"""% \ (EncodeValue(sCombinedProductID), EncodeValue(sCombinedProductID), \ EncodeValue(sProviderID), aFields[conFieldProductDetection])) req.write ("") req.write ("") def GetDependenciesXML(sProviderID, aDependencyIDs): # global itemsindex, items str = "" if aDependencyIDs is not None: if len(aDependencyIDs) > 0: str = str + "" for sDependencyID in aDependencyIDs: sDependencyID = sProviderID + "." + sDependencyID if itemsindex.has_key(sDependencyID): sItemGuid = itemsindex[sDependencyID][0] if items.has_key(sItemGuid): aFields = items[sItemGuid] str = str + """%s"""% \ (sDependencyID, aFields[conFieldItemName], aFields[conFieldItemPublisherName]) str = str + "" return str def DisplayItems(req, sItemID, iCurrentDepth): # global itemsindex, items, items_sent, last_sProviderID global last_sProviderID sProviderID = string.split(sItemID, '.')[0] if sProviderID <> last_sProviderID: LoadItems(sProviderID) last_sProviderID = sProviderID if itemsindex.has_key(sItemID): aParts = itemsindex[sItemID] sItemGuid = aParts[0] if aParts[1] <> "": aDependencies = string.split(aParts[1], ',') else: aDependencies = None if items.has_key(sItemGuid): aFields = items[sItemGuid] sCombinedProductID = GetProductFromID(sItemID) #If itemIsApproved(aFields, banneditems) Then if itemIsApproved(aFields,g_sLocale) and (not items_sent.has_key(sItemID)): #if itemIsApproved(sItemGuid) and (not items_sent.has_key(sItemID)): req.write( """com.microsoft%s"""% \ (aFields[conFieldItemInstallable], EncodeValue(sItemID), GetItemNameFromID(sItemID), aFields[conFieldItemDetection])) if aDependencies is not None: req.write(GetDependenciesXML(sProviderID, aDependencies)) req.write("") items_sent[sItemID] = "" #store that this item has been outputed into the XML stream if (aDependencies is not None) and iCurrentDepth < con_iMaxDependencyDepth: for sDependencyID in aDependencies: DisplayItems (sProviderID + "." + sDependencyID, iCurrentDepth + 1) # recurse for each dependency #End If def DoItemsQuery(req, query, sysinfo): sPlatform = GetPlatformString(sysinfo) #print sPlatform items_query = [] for node in query.childNodes: if node.nodeName == 'parentItems': for cnode in node.childNodes: if cnode.nodeName == 'item': data = "" for tn in cnode.childNodes: if tn.nodeType == tn.TEXT_NODE: data = data + tn.data data = string.strip(data) if data <> "": items_query.append(data) if items_query == []: return ReturnEmptyCatalog(req) req.write ("""ItemsProvider""") product2items = {} for item in items_query: sitem = string.split(item, '.')[0] for line in open(product2items_file%(sitem,), "rt").readlines(): pos = string.find(line, ',') if pos > 0: key = line[:pos] if not product2items.has_key(key): product2items[key] = string.split(string.strip(line[pos+1:]), ',') aUpdateIDs = None LoadApprovedItems() #new for item in items_query: aParentage = string.split(item, '.') sProviderID = aParentage[0] sProductID = aParentage[1] sPlat = sPlatform sUpdateIDs = "" for iCount in xrange(12): newkey = item + "." + sPlat # open("/tmp/plat.log", "a").write(newkey+'\n') # if string.find(newkey, 'ver_platform_win32_nt.5.2.x86.en...3790..')>0: # print "!!!",iCount,"!!!" if product2items.has_key(newkey): aUpdateIDs = product2items[newkey] break sPlat = GetMoreGeneralPlatform(sPlatform, iCount+1) if aUpdateIDs is not None: for sUpdateID in aUpdateIDs: # open("/tmp/ids.log", "a").write(sUpdateID+'\n') DisplayItems(req, sProviderID + "." + sUpdateID, 0) req.write ("") def DoItemDetailsQuery(req, query): # global itemsindex, items, last_sProviderID, g_sLocale global last_sProviderID, g_sLocale, bMaintainContentLocally items_query = [] for node in query.childNodes: if node.nodeName == 'parentItems': for cnode in node.childNodes: if cnode.nodeName == 'item': data = "" for tn in cnode.childNodes: if tn.nodeType == tn.TEXT_NODE: data = data + tn.data data = string.strip(data) if data <> "": items_query.append(data) if items_query == []: return ReturnEmptyCatalog(req) req.write("""""") bFirstTime = True #flag to set up correct firsttime xml tags if g_bUseApprovedItemsList: sLocalCodebaseUrlPrefix = CabPoolURL sLocalEulaUrlPrefix = sLocalCodebaseUrlPrefix + "/eula/" sLocalDetailsUrlPrefix = sLocalCodebaseUrlPrefix + "/rtf/" else: bMaintainContentLocally = False for oCombinedID in items_query: sCombinedID = oCombinedID sProviderID = string.split(sCombinedID, '.')[0] if sProviderID <> last_sProviderID: LoadItems(sProviderID, 4) last_sProviderID = sProviderID if not bFirstTime: req.write ("") else: bFirstTime = False req.write("""com.microsoft"""% \ (EncodeValue(sProviderID), EncodeValue(sProviderID), GetProviderTitle(sProviderID, g_sLocale))) if itemsindex.has_key(sCombinedID): aItemIndex = itemsindex[sCombinedID] sItemGUID = aItemIndex[0] if sItemGUID <> "": if aItemIndex[1] <> "": aDependencies = string.split(aItemIndex[1], ',') else: aDependencies = None aItemFields = items[sItemGUID] sItemStringGUID = GetItemStringGUID(sCombinedID, g_sLocale) # conFieldItemStringsTitle, conFieldItemStringsDetailsURL, conFieldItemStringsEULA, conFieldItemStringsDescription) vItemDetails = itemstrings[sItemStringGUID] g_sUserLocale = g_sLocale g_sLocale = "en" if vItemDetails[conFieldItemStringsTitle] == "": vItemDetails[conFieldItemStringsTitle] = GetItemTitle(sCombinedID) if vItemDetails[conFieldItemStringsDescription] == "": vItemDetails[conFieldItemStringsDescription] = GetItemDescription(sCombinedID) if vItemDetails[conFieldItemStringsDetailsURL] == "": vItemDetails[conFieldItemStringsDetailsURL] = GetItemDetailsURL(sCombinedID) g_sLocale = g_sUserLocale sInstallation = aItemFields[conFieldItemInstallation] if g_bUseApprovedItemsList: if bMaintainContentLocally: sInstallation = AdjustInstallationCodeBase(sInstallation, sLocalCodebaseUrlPrefix) vItemDetails[conFieldItemStringsEULA] = sLocalEulaUrlPrefix + vItemDetails[conFieldItemStringsEULA] else: if string.find(string.lower(vItemDetails[conFieldItemStringsEULA]), "http://") > 0: vItemDetails[conFieldItemStringsEULA] = conEULAURL &+vItemDetails[conFieldItemStringsEULA] res = """%s""" + \ """%s""" + \ """%s"""; req.write(res % \ (aItemFields[conFieldItemInstallable].encode("utf-8"), EncodeValue(sCombinedID).encode("utf-8"), aItemFields[conFieldItemName].encode("utf-8"), \ aItemFields[conFieldItemPublisherName].encode("utf-8"), GetPlatformNameFromID(sCombinedID).encode("utf-8"), \ GetProcessorArchitectureFromID(sCombinedID).encode("utf-8"), GetPlatformMajorFromID(sCombinedID).encode("utf-8"), \ GetPlatformMinorFromID(sCombinedID).encode("utf-8"), GetBuildFromID(sCombinedID).encode("utf-8"), GetServicePackMajorFromID(sCombinedID).encode("utf-8"), \ GetServicePackMinorFromID(sCombinedID).encode("utf-8"), aItemFields[conFieldItemPriority].encode("utf-8"), \ aItemFields[conFieldItemHidden].encode("utf-8"), aItemFields[conFieldItemSize].encode("utf-8"), \ vItemDetails[conFieldItemStringsTitle].encode("utf-8"), vItemDetails[conFieldItemStringsEULA].encode("utf-8"), \ vItemDetails[conFieldItemStringsDescription].encode("utf-8"), sInstallation)) #if aDependencies is not None: # print GetDependenciesXML(sProviderID, aDependencies) req.write("") req.write("") #def handler(req): #req.content_type = "text/xml; charset=UTF-8" print "Content-type: text/xml; charset=UTF-8\n" #data = open("req2.xml", "rt").read() data = "" if os.environ['REQUEST_METHOD'] == "POST": datalength = os.environ['CONTENT_LENGTH'] data = sys.stdin.read(int(datalength)) global CabPoolURL if os.environ.has_key('SERVER_ADDR'): server_name = os.environ['SERVER_ADDR'] else: if os.environ.has_key('SERVER_NAME'): server_name = os.environ['SERVER_NAME'] else: server_name = "" CabPoolURL = "http://" + server_name + "/content" if len(data) > con_iMaxRequestLength or string.strip(data) == "": ReturnEmptyCatalog(req) sys.exit() # return ReturnEmptyCatalog(req) dom = xml.dom.minidom.parseString(data) #req = dom.getElementsByTagName("SOAP:Envelope/SOAP:Body/GetManifest") g_oRequestXML = dom.getElementsByTagName("GetManifest") if not g_oRequestXML: ReturnEmptyCatalog(req) sys.exit() # return ReturnEmptyCatalog(req) oClientInfo = None oUserLocaleNode = None g_oQueryNode = None for nodes in g_oRequestXML: for node in nodes.childNodes: if node.nodeName == 'clientInfo': oClientInfo = node if node.nodeName == 'systemInfo': oSystemInfo = node for cnode in node.childNodes: if cnode.nodeName == 'locale' and cnode.hasAttribute("context") and cnode.getAttribute("context")=='USER': for ccnode in cnode.childNodes: if ccnode.nodeName == 'language': oUserLocaleNode = ccnode if node.nodeName == 'query': for cnode in node.childNodes: if cnode.nodeName == 'dObjQueryV1': g_oQueryNode = cnode if (oClientInfo is not None) and (oClientInfo.hasAttribute("clientName")): g_sClientName = string.lower(oClientInfo.getAttribute("clientName")) else: ReturnEmptyCatalog(req) if (oUserLocaleNode is not None): global g_sLocale g_sUserLocale = "" for tn in oUserLocaleNode.childNodes: if tn.nodeType == tn.TEXT_NODE: g_sUserLocale = g_sUserLocale + tn.data g_sLocale = ConvertLocale(g_sUserLocale) else: ReturnEmptyCatalog(req) if (g_oQueryNode is not None) and g_oQueryNode.hasAttribute('procedure'): sProcedure = string.lower(g_oQueryNode.getAttribute("procedure")) else: ReturnEmptyCatalog(req) if os.environ.has_key('REMOTE_ADDR'): remote_ip = os.environ['REMOTE_ADDR'] else: remote_ip = "" if sProcedure == 'providers': if susdebug: open("/tmp/sus-providers.log", "a").write(remote_ip + "\n" + time.strftime('%X %x %Z') + "\n" + data + "\n------\n") DoProvidersQuery(req) elif sProcedure == 'products': if susdebug: open("/tmp/sus-products.log", "a").write(remote_ip + "\n" + time.strftime('%X %x %Z') +"\n" + data + "\n------\n") DoProductsQuery(req, g_oQueryNode) elif sProcedure == 'items': if susdebug: open("/tmp/sus-items.log", "a").write(remote_ip + "\n" + time.strftime('%X %x %Z') +"\n" + data + "\n------\n") DoItemsQuery(req, g_oQueryNode, oSystemInfo) elif sProcedure == 'itemdetails': if susdebug: open("/tmp/sus-itemdetails.log", "a").write(remote_ip + "\n" + time.strftime('%X %x %Z') + "\n" + data + "\n------\n") DoItemDetailsQuery(req, g_oQueryNode) else: ReturnEmptyCatalog(req) dom.unlink() # return apache.OK