Index: main/plugin-syndication/i18n/messages_en.xml
===================================================================
--- main/plugin-syndication/i18n/messages_en.xml	(revision 40116)
+++ main/plugin-syndication/i18n/messages_en.xml	(working copy)
@@ -26,6 +26,9 @@
 	<message key="SYNDICATION_SERVICE_READ_RSS_TITLE">Title</message>
 	<message key="SYNDICATION_SERVICE_READ_RSS_TITLE_DESC">Feed title (optional)</message>
 	
+	<message key="SYNDICATION_SERVICE_READ_RSS_ID">Identifier</message>
+    <message key="SYNDICATION_SERVICE_READ_RSS_ID_DESC">Feed identifier automatically generated</message>
+	
 	<message key="SYNDICATION_SERVICE_READ_RSS_URL">Feed URL</message>
 	<message key="SYNDICATION_SERVICE_READ_RSS_URL_DESC">Feed URL (http://...)</message>
 	
Index: main/plugin-syndication/i18n/messages_fr.xml
===================================================================
--- main/plugin-syndication/i18n/messages_fr.xml	(revision 40116)
+++ main/plugin-syndication/i18n/messages_fr.xml	(working copy)
@@ -26,6 +26,9 @@
 	<message key="SYNDICATION_SERVICE_READ_RSS_TITLE">Titre</message>
 	<message key="SYNDICATION_SERVICE_READ_RSS_TITLE_DESC">Titre du flux RSS (optionnel)</message>
 	
+	<message key="SYNDICATION_SERVICE_READ_RSS_ID">Identifiant</message>
+    <message key="SYNDICATION_SERVICE_READ_RSS_ID_DESC">Identifiant du flux RSS généré automatiquement</message>
+	
 	<message key="SYNDICATION_SERVICE_READ_RSS_URL">URL du flux</message>
 	<message key="SYNDICATION_SERVICE_READ_RSS_URL_DESC">URL du flux RSS (http://...)</message>
 	
Index: main/plugin-syndication/pages/services/feed/utils/preference.xsl
===================================================================
--- main/plugin-syndication/pages/services/feed/utils/preference.xsl	(revision 40116)
+++ main/plugin-syndication/pages/services/feed/utils/preference.xsl	(working copy)
@@ -117,6 +117,7 @@
                 <input type="checkbox" name="feed-check-{$position}" id="feed-config-{$uniqueId}-check-{$position}">
                     <xsl:if test="@isSelected = 'true'"><xsl:attribute name="checked">checked</xsl:attribute></xsl:if>
                 </input>
+                <input type="hidden" name="feed-id-{$position}" id="feed-config-{$uniqueId}-id-{$position}" value="{@feedId}"/>
             </div>
             <div class="label">
                 <label for="feed-config-{$uniqueId}-check-{$position}"><xsl:value-of select="$name"/></label>
@@ -132,6 +133,7 @@
                 <input type="checkbox" name="feed-check-{$position}" id="feed-config-{$uniqueId}-check-{$position}">
                     <xsl:if test="@isSelected = 'true'"><xsl:attribute name="checked">checked</xsl:attribute></xsl:if>
                 </input>
+                <input type="hidden" name="feed-id-{$position}" id="feed-config-{$uniqueId}-id-{$position}" value="{@feedId}"/>
             </div>
             <div class="label">
                 <input type="input" onkeyup="check_{$uniqueId}('feed-config-{$uniqueId}-check-{$position}')" name="feed-url-{$position}" id="feed-config-{$uniqueId}-url-{$position}" value="{@feedUrl}"/>
@@ -217,6 +219,10 @@
                     while (checkBox[0] != null)
                     {
                         data["feed-check-" + i] = checkBox[0].checked;
+                        
+                        var idFeedInput = $j("#feed-config-<xsl:value-of select="$uniqueId"/>-id-" + i);
+                        data["feed-id-" + i] = idFeedInput[0].value;
+                        
                         var inputUrl = $j("#feed-config-<xsl:value-of select="$uniqueId"/>-url-" + i);
                         if (inputUrl[0] != null)
                         {
Index: main/plugin-syndication/plugin.xml
===================================================================
--- main/plugin-syndication/plugin.xml	(revision 40116)
+++ main/plugin-syndication/plugin.xml	(working copy)
@@ -30,6 +30,15 @@
         </components>
         
     	<extensions>
+    	    <extension id="org.ametys.syndication.Widget"
+                       point="org.ametys.cms.workspace.uitool.StaticFileImportsManager"
+                       class="org.ametys.cms.workspace.uitool.StaticFileImportsClientSideElement">
+                       
+                <scripts>
+                    <file>js/org/ametys/syndication/widget/GenerateIdWidget.i18n.js</file>
+                </scripts>
+            </extension>
+    	
             <extension point="org.ametys.runtime.plugins.core.right.RightsExtensionPoint"
                        id="org.ametys.plugins.syndication.service.rss.rights">
                 <right id="Syndication_Right_Service_RSS">
@@ -140,6 +149,11 @@
                             <description i18n="true">SYNDICATION_SERVICE_READ_RSS_FO_GROUP_DESC</description>
                             <widget>fogroup</widget>
                         </parameter>
+                        <parameter name="id" type="string">
+                            <label i18n="true">SYNDICATION_SERVICE_READ_RSS_ID</label>
+                            <description i18n="true">SYNDICATION_SERVICE_READ_RSS_ID_DESC</description>
+                            <widget>generate-id</widget>
+                        </parameter>
                     </repeater>
                     <parameter name="nb-feed-user" type="long">
                         <label i18n="true">SYNDICATION_SERVICE_READ_RSS_NB_FLUX_CUSTOM</label>
Index: main/plugin-syndication/resources/js/org/ametys/syndication/widget/GenerateIdWidget.i18n.js
===================================================================
--- main/plugin-syndication/resources/js/org/ametys/syndication/widget/GenerateIdWidget.i18n.js	(revision 0)
+++ main/plugin-syndication/resources/js/org/ametys/syndication/widget/GenerateIdWidget.i18n.js	(revision 0)
@@ -0,0 +1,43 @@
+/*
+ *  Copyright 2016 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+Ext.namespace('org.ametys.syndication.widget');
+
+//Register widget
+org.ametys.utils.Widgets.registerWidget ('string', 'generate-id', 'org.ametys.syndication.widget.GenerateIdWidget');
+
+org.ametys.syndication.widget.GenerateIdWidget = function(config, enumeratedValues) 
+{
+	org.ametys.syndication.widget.GenerateIdWidget.superclass.constructor.call(this, config, enumeratedValues);
+}; 
+
+Ext.extend(org.ametys.syndication.widget.GenerateIdWidget, Ext.form.Hidden, {});
+
+org.ametys.syndication.widget.GenerateIdWidget.prototype.onRender = function (ct, position)
+{
+	org.ametys.syndication.widget.GenerateIdWidget.superclass.onRender.call(this, ct, position);
+}
+
+org.ametys.syndication.widget.GenerateIdWidget.prototype.setValue = function (value)
+{
+	if (!value || value == '')
+	{
+		// Generate ramdom key with 6 numbers if empty
+		value = Math.floor((Math.random() * 0.9 + 0.1) * 1000000);
+	}
+	
+	org.ametys.syndication.widget.GenerateIdWidget.superclass.setValue.call(this, value);
+}
Index: main/plugin-syndication/src/org/ametys/plugins/syndication/FeedsGenerator.java
===================================================================
--- main/plugin-syndication/src/org/ametys/plugins/syndication/FeedsGenerator.java	(revision 40116)
+++ main/plugin-syndication/src/org/ametys/plugins/syndication/FeedsGenerator.java	(working copy)
@@ -60,7 +60,7 @@
     public static final String USER_PREF_RSS_URL_KEY = "user-pref-rss-urls";
     
     /** User pref key for positions */
-    public static final String USER_PREF_RSS_POSITION_KEY = "user-pref-rss-positions";
+    public static final String USER_PREF_RSS_ID_KEY = "user-pref-rss-positions";
     
     private static HashMap<String, Integer> _lifeTimes = new HashMap<String, Integer>();
     static 
@@ -121,11 +121,11 @@
         CompositeMetadata serviceParameters = zoneItem.getServiceParameters();
 
         List<String> urlList = new ArrayList<String>();
-        List<String> positionList = new ArrayList<String>();
+        List<String> idList = new ArrayList<String>();
         try
         {
             urlList = _getListUrl(login, storageContext, contextVars);
-            positionList = _getListPosition(login, storageContext, contextVars);
+            idList = _getListId(login, storageContext, contextVars);
         }
         catch (UserPreferencesException e1)
         {
@@ -133,12 +133,12 @@
         }
         
         contentHandler.startDocument();
-        _saxAllFeed(request, zoneItem, serviceParameters, urlList, positionList);
+        _saxAllFeed(request, zoneItem, serviceParameters, urlList, idList);
         contentHandler.endDocument();
     }
     
     // Sax all the feed depend on the service parameters
-    private void _saxAllFeed(Request request, ZoneItem zoneItem, CompositeMetadata serviceParameters, List<String> urlList, List<String> userSelectedFeedsPositions) throws SAXException
+    private void _saxAllFeed(Request request, ZoneItem zoneItem, CompositeMetadata serviceParameters, List<String> urlList, List<String> userSelectedFeedsId) throws SAXException
     {
         String defaultLengthValueAsString = serviceParameters.getString("length");
         if (StringUtils.isEmpty(defaultLengthValueAsString))
@@ -176,90 +176,72 @@
         
         XMLUtils.startElement(contentHandler, "rssFeeds", atts);
         
-        long totalFeed = listFeeds.size() + nbMaxUser;
-        
-        _saxFeeds(totalFeed, listFeeds, urlList, nbMaxFeedFullSaxed, defaultLengthValueAsString, defaultLifeTime, serviceParameters, userSelectedFeedsPositions);
-        _saxFeedsConfig(totalFeed, nbMaxUser, listFeeds, urlList, userSelectedFeedsPositions);
+        _saxFeeds(nbMaxUser, listFeeds, urlList, nbMaxFeedFullSaxed, defaultLengthValueAsString, defaultLifeTime, serviceParameters, userSelectedFeedsId);
+        _saxFeedsConfig(nbMaxUser, listFeeds, urlList, userSelectedFeedsId);
         
         XMLUtils.endElement(contentHandler, "rssFeeds");
     }
     
-    private void _saxFeedsConfig(long totalFeed, long nbMaxUser, List<CompositeMetadata> listFeeds, List<String> urlList, List<String> userSelectedFeedsPositions) throws SAXException
+    private void _saxFeedsConfig(long nbMaxUser, List<CompositeMetadata> listFeeds, List<String> urlList, List<String> userSelectedFeedsId) throws SAXException
     {
-        int nbFeedCustom = 0;
-        for (int position = 0; position < totalFeed; position++)
+        for (CompositeMetadata rssFeed : listFeeds)
         {
-            CompositeMetadata rssFeed = null;
-            if (position < listFeeds.size())
-            {
-                rssFeed = listFeeds.get(position);
-            }
-            
-            Boolean isSelected = userSelectedFeedsPositions.contains(String.valueOf(position + 1));
-
-            if (rssFeed != null) // Feed from service parameters
+            _saxInfoFeed(rssFeed.getString("url"), rssFeed.getString("title"), rssFeed.getString("id"), false, userSelectedFeedsId.contains(rssFeed.getString("id")));
+        }
+        
+        for (int i = 1; i <= nbMaxUser; i++)
+        {
+            boolean isSelected = userSelectedFeedsId.contains("feed-url" + i) || userSelectedFeedsId.contains(String.valueOf(i + listFeeds.size()));
+            if (i <= urlList.size())
             {
-                _saxInfoFeed(rssFeed.getString("url"), rssFeed.getString("title"), false, isSelected); // Sax the user preference form
+                String url  = urlList.get(i - 1);
+                _saxInfoFeed(url, "", "feed-url" + i, true, isSelected);
             }
-            else // Feed from user preference
+            else
             {
-                if (position - listFeeds.size() < urlList.size())
-                {
-                    _saxInfoFeed(urlList.get(position - listFeeds.size()), "", true, isSelected); // Sax the user preference form
-                }
-                else if (nbFeedCustom < nbMaxUser)
-                {
-                    _saxInfoFeed("", "", true, isSelected); // Sax the user preference form (empty input)
-                }
-                nbFeedCustom++;
+                _saxInfoFeed("", "", "feed-url" + i, true, isSelected);
             }
         }
     }
     
-    private void _saxFeeds(long totalFeed, List<CompositeMetadata> listFeeds, List<String> urlList, long nbMaxFeedFullSaxed, String defaultLengthValueAsString, String defaultLifeTime, CompositeMetadata serviceParameters,  List<String> userSelectedFeedsPositions)
+    private void _saxFeeds(int nbMaxUser, List<CompositeMetadata> listFeeds, List<String> urlList, long nbMaxFeedFullSaxed, String defaultLengthValueAsString, String defaultLifeTime, CompositeMetadata serviceParameters,  List<String> userSelectedFeedsId)
     {
         int nbFeedFullSaxed = 0;
-        for (int position = 0; position < totalFeed; position++)
+        for (CompositeMetadata rssFeed : listFeeds)
         {
-            CompositeMetadata rssFeed = null;
-            if (position < listFeeds.size())
+            boolean isSelected = userSelectedFeedsId.contains(rssFeed.getString("id"));
+            if ((nbFeedFullSaxed < nbMaxFeedFullSaxed || nbMaxFeedFullSaxed == 0)
+                    && (userSelectedFeedsId.isEmpty() || isSelected))
             {
-                rssFeed = listFeeds.get(position);
+                nbFeedFullSaxed++;
+                _saxFullInfoFeed(rssFeed, isSelected, defaultLengthValueAsString, defaultLifeTime); // Sax all informations
             }
-            
-            // Check if the max number of feed to sax was not reached
-            // and if the feed has been selected by the visitor
-            if ((nbFeedFullSaxed < nbMaxFeedFullSaxed || nbMaxFeedFullSaxed == 0)
-                && (userSelectedFeedsPositions.isEmpty() || userSelectedFeedsPositions.contains(String.valueOf(position + 1))))
+        }
+        
+        for (int i = 1; i <= nbMaxUser; i++)
+        {
+            if (i <= urlList.size())
             {
-                if (rssFeed != null) // Feed from service parameters
+                String url = urlList.get(i - 1);
+                boolean isSelected = userSelectedFeedsId.contains("feed-url" + i) || userSelectedFeedsId.contains(String.valueOf(i + listFeeds.size()));
+                if ((nbFeedFullSaxed < nbMaxFeedFullSaxed || nbMaxFeedFullSaxed == 0)
+                        && (userSelectedFeedsId.isEmpty() || isSelected))
                 {
-                    Boolean isSelected = userSelectedFeedsPositions.contains(String.valueOf(position + 1));
-
-                    _saxFullInfoFeed(rssFeed, isSelected, defaultLengthValueAsString, defaultLifeTime); // Sax all informations
+                    nbFeedFullSaxed++;
+                    _saxFullInfoFeedCustom(serviceParameters, url, defaultLengthValueAsString, isSelected); // Sax all informations
                 }
-                else // Feed from user preference
-                {
-                    if (position - listFeeds.size() < urlList.size())
-                    {
-                        String urlFeed = urlList.get(position - listFeeds.size());
-                        Boolean isSelected = userSelectedFeedsPositions.contains(String.valueOf(position + 1));
-                        
-                        _saxFullInfoFeedCustom(serviceParameters, urlFeed, defaultLengthValueAsString, isSelected); // Sax all informations
-                    }
-                }
-                nbFeedFullSaxed++;
             }
         }
     }
     
     // Sax few info from the feed for the user preference form
-    private void _saxInfoFeed(String url, String name, Boolean isCustom, Boolean isSelected) throws SAXException
+    private void _saxInfoFeed(String url, String name, String feedId, Boolean isCustom, Boolean isSelected) throws SAXException
     {
         AttributesImpl atts = new AttributesImpl();
 
         atts.addCDATAAttribute("feedUrl", url);
         atts.addCDATAAttribute("feedName", name);
+        atts.addCDATAAttribute("feedId", feedId);
         atts.addCDATAAttribute("isCustom", String.valueOf(isCustom));
         atts.addCDATAAttribute("isSelected", String.valueOf(isSelected));
 
@@ -328,7 +310,7 @@
         List<String> urlAsList = new ArrayList<String>();
         if (StringUtils.isNotEmpty(urls))
         {
-            String[] urlsAsArray = StringUtils.split(urls, ",");
+            String[] urlsAsArray = urls.split(",");
             for (String url : urlsAsArray)
             {
                 urlAsList.add(URLDecoder.decode(url, "utf-8"));
@@ -339,12 +321,12 @@
     }
     
     // Get the list of chosen feed (position) from the user preferences
-    private List<String> _getListPosition(String login, String storageContext, Map<String, String> contextVars) throws UserPreferencesException
+    private List<String> _getListId(String login, String storageContext, Map<String, String> contextVars) throws UserPreferencesException
     {
-        String positions = _userPrefManager.getUserPreferenceAsString(login, storageContext, contextVars, USER_PREF_RSS_POSITION_KEY);
+        String positions = _userPrefManager.getUserPreferenceAsString(login, storageContext, contextVars, USER_PREF_RSS_ID_KEY);
         if (StringUtils.isNotEmpty(positions))
         {
-            String[] positionsAsArray = StringUtils.split(positions, ",");
+            String[] positionsAsArray = positions.split(",");
             return Arrays.asList(positionsAsArray);
         }
         
Index: main/plugin-syndication/src/org/ametys/plugins/syndication/SetRssFeedUserPreferencesAction.java
===================================================================
--- main/plugin-syndication/src/org/ametys/plugins/syndication/SetRssFeedUserPreferencesAction.java	(revision 40116)
+++ main/plugin-syndication/src/org/ametys/plugins/syndication/SetRssFeedUserPreferencesAction.java	(working copy)
@@ -79,12 +79,12 @@
         Map<String, String> contextVars = _getContextVars(siteName, language);
         
         Map<String, String> values = new HashMap<String, String>();
-        String positions = _getPositions(request);
+        String ids = _getIds(request);
         
         int nbMaxCheck = Integer.parseInt(request.getParameter("nbMaxCheck"));
-        if (StringUtils.split(positions, ",").length <= nbMaxCheck || nbMaxCheck == 0)
+        if (StringUtils.split(ids, ",").length <= nbMaxCheck || nbMaxCheck == 0)
         {
-            values.put(FeedsGenerator.USER_PREF_RSS_POSITION_KEY, _getPositions(request));
+            values.put(FeedsGenerator.USER_PREF_RSS_ID_KEY, _getIds(request));
             values.put(FeedsGenerator.USER_PREF_RSS_URL_KEY, _getUrls(request));
             
             _userPrefManager.setUserPreferences(login, storageContext, contextVars, values);
@@ -118,12 +118,12 @@
         return StringUtils.join(urls, ",");
     }
     
-    private String _getPositions(Request request)
+    private String _getIds(Request request)
     {
         int nbFeed = Integer.parseInt(request.getParameter("nbFeedService"));
         int nbFeedUser = Integer.parseInt(request.getParameter("nbMaxUser"));
 
-        List<Integer> positions = new ArrayList<Integer>();
+        List<String> ids = new ArrayList<String>();
         for (int i = 1; i <= (nbFeed + nbFeedUser); i++)
         {
             String checked = request.getParameter("feed-check-" + i);
@@ -131,12 +131,12 @@
             {
                 if (checked.equals("true") || checked.equals("on"))
                 {
-                    positions.add(i);
+                    ids.add(request.getParameter("feed-id-" + i));
                 }
             }
         }
         
-        return StringUtils.join(positions, ",");
+        return StringUtils.join(ids, ",");
     }
     
     private Map<String, String> _getContextVars(String siteName, String language)
